Bagaimana cara mengaktifkan onListItemClick di Listactivity dengan tombol dalam daftar?

89

Saya memiliki ListActivity sederhana yang menggunakan ListAdapter kustom untuk menghasilkan tampilan dalam daftar. Biasanya ListAdapter hanya akan mengisi tampilan dengan TextView, tetapi sekarang saya ingin meletakkan tombol di sana juga.

Namun menurut pemahaman dan pengalaman saya, meletakkan tampilan yang dapat difokuskan di item daftar mencegah pengaktifan onListItemClick () di ListActivity saat item daftar diklik. Tombol tersebut masih berfungsi secara normal dalam item daftar, tetapi ketika sesuatu selain tombol ditekan, saya ingin onListItemClick dipicu.

Bagaimana saya bisa membuat ini bekerja?

CodeFusionMobile
sumber
5
Solusi Anda dengan Focusability turunan sangat membantu, Anda harus menambahkannya sebagai jawaban dan menerimanya!
Maksym Gontar
@Max Alasan saya tidak melakukannya adalah karena ini benar-benar praktik yang buruk, sebuah solusi. Jika saya pernah menemukan solusi sehat permanen, saya akan membuat jawaban itu (jika saya ingat bahwa saya menulis pertanyaan ini setahun yang lalu :))
CodeFusionMobile
Saya juga ingin melihat solusi yang Anda miliki. Saya telah mencoba mengatur fokus turunan dan tidak dapat membuatnya bekerja dengan tombol. Juga saya telah mencoba untuk meletakkan GridView (dengan ImageView) di baris daftar dan itu memiliki masalah serupa.
MrPurpleStreak
Jawaban IMHO yang saya berikan adalah solusi yang jauh lebih elegan untuk masalah daripada yang diusulkan oleh Ramps dan Praveen. PsTidak mencoba untuk menghidupkan kembali pertanyaan yang terlupakan di sini tetapi saya melihat Anda belum menerima jawaban apa pun; D
Ewoks
@CodeFusionMobile Bisakah Anda menerima jawaban Ewoks? Jawaban dengan suara terbanyak adalah cacat karena menonaktifkan animasi onclick untuk elemen ListView (yang berubah menjadi biru). Ini akan menghemat waktu pengembang lain yang dihabiskan untuk mencoba jawaban teratas, mengetahui bahwa itu cacat, dan kemudian pergi ke Ewoks's.
1 ''

Jawaban:

99

seperti yang saya tulis di solusi komentar sebelumnya adalah dengan setFocusable (false) di ImageButton.

Ada solusi yang lebih elegan mencoba menambahkan android:descendantFocusability="blocksDescendants" tata letak root elemen daftar. Itu akan membuat klik onListItem menjadi mungkin dan secara terpisah Anda dapat menangani klik Tombol atau ImageButton

Semoga membantu;)

Bersulang

Ewoks
sumber
3
android:descendantFocusability="blocksDescendants"sempurna.
Matthew Mitchell
1
kamu, temanku, adalah pahlawan pribadiku. Anda harus menjadi yang terpilih teratas! ini jauh lebih baik untuk hampir semua kasus!
OschtärEi
Ini harus menjadi jawaban yang diterima. Ini bekerja dengan sempurna untuk saya. Sepertinya semua tampilan dalam item daftar harus tidak dapat difokuskan dan yang ini melakukannya tanpa menyetel masing-masing secara individual.
bergegas
1
Ini sepertinya tidak berhasil untuk saya. Yang Anda maksud dengan tata letak root adalah tata letak baris atau tempat listview ditentukan? Bagaimanapun, saya mencoba semua kemungkinan kombinasi .. tidak berfungsi :(
GreenBee
"Root layout of list element" seperti yang saya tulis .. Jadi katakanlah Anda memiliki daftar dan terdiri dari tata letak (sebut saja tata letak root elemen daftar) yang memiliki beberapa Tombol, ImageButton, TextVeiw ..
Ewoks
59

Saya harap saya dapat membantu di sini. Saya berasumsi bahwa Anda memiliki tata letak khusus untuk item listView, dan tata letak ini terdiri dari tombol dan beberapa tampilan lain - seperti TextView, ImageView atau apa pun. Sekarang Anda ingin mengaktifkan peristiwa berbeda pada klik tombol dan peristiwa berbeda diaktifkan pada semua yang diklik.

Anda bisa mencapainya tanpa menggunakan onListItemClick () dari ListActivity Anda.
Inilah yang harus Anda lakukan:

Anda menggunakan tata letak khusus, jadi mungkin Anda mengganti metode getView () dari adaptor khusus Anda. Triknya adalah mengatur pendengar yang berbeda untuk tombol Anda dan berbeda untuk keseluruhan tampilan (baris Anda). Lihat contohnya:

private class MyAdapter extends ArrayAdapter<String> implements OnClickListener {

    public MyAdapter(Context context, int resource, int textViewResourceId,
            List<String> objects) {
        super(context, resource, textViewResourceId, objects);
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        String text = getItem(position);
        if (null == convertView) {
            convertView = mInflater.inflate(R.layout.custom_row, null);
        }
        //take the Button and set listener. It will be invoked when you click the button.
        Button btn = (Button) convertView.findViewById(R.id.button);
        btn.setOnClickListener(this);
        //set the text... not important     
        TextView tv = (TextView) convertView.findViewById(R.id.text);
        tv.setText(text);
        //!!! and this is the most important part: you are settin listener for the whole row
        convertView.setOnClickListener(new OnItemClickListener(position));
        return convertView;
    }

    @Override
    public void onClick(View v) {
        Log.v(TAG, "Row button clicked");
    }
}

Kelas OnItemClickListener Anda dapat dideklarasikan seperti di sini:

private class OnItemClickListener implements OnClickListener{       
    private int mPosition;
    OnItemClickListener(int position){
        mPosition = position;
    }
    @Override
    public void onClick(View arg0) {
        Log.v(TAG, "onItemClick at position" + mPosition);          
    }       
}

Tentu saja Anda mungkin akan menambahkan beberapa parameter lagi ke konstruktor OnItemClickListener.
Dan satu hal penting - implementasi getView yang ditunjukkan di atas cukup jelek, biasanya Anda harus menggunakan pola ViewHolder untuk menghindari panggilan findViewById .. tetapi Anda mungkin sudah mengetahuinya.
File custom_row.xml saya adalah RelativeLayout dengan Tombol id "button", TextView of id "text" dan ImageView of id "image" - hanya untuk memperjelas.
Salam!

Landai
sumber
9
Solusi saya berakhir dengan cara lain. Saya memecahkan masalah dengan menyetel properti Focusability turunan dari tata letak baris daftar untuk memblokir turunan dan tiba-tiba berhasil. Sekarang saya menggunakan simpleCursorAdapter dengan viewbinder khusus yang dilampirkan untuk melakukan pengaturan acara dan hal-hal mewah lainnya yang terkait dengan tombol.
CodeFusionMobile
3
Saya menggunakan solusi ini. Namun, peringatan: jika penangan onClick Anda menyebabkan konten daftar berubah, yang akan mengakibatkan getView dipanggil DAN jika widget Anda berstatus state (seperti ToggleButton atau Kotak Centang), DAN getView menyetel status itu, Anda mungkin perlu menyetelOnClickListener (null) sebelum Anda mengubah status di onView, untuk menghindari efek loop.
Pierre-Luc Paour
3
bagaimana solusi saya? Saya memiliki kesan yang lebih elegan dan dapat diterapkan dengan lebih mudah kapanpun kita membutuhkannya ..
Ewoks
komentar pertama harus diterima sebagai jawaban, jadi orang-orang seperti saya tidak perlu berjam-jam untuk menemukannya
keybee
Terima kasih! Ini berguna. Saya menyukainya sebagai alternatif yang lebih terlokalisasi untuk fokus: pendekatan blockDescendants yang dijelaskan di utas lain.
Yoav Shapira
18

Saat ListView kustom berisi elemen yang dapat difokuskan, onListItemClick tidak akan berfungsi (menurut saya itu adalah perilaku yang diharapkan). Hapus saja fokus dari tampilan kustom, ini akan melakukan trik:

Sebagai contoh:

public class ExtendedCheckBoxListView extends LinearLayout {

    private TextView mText;
    private CheckBox mCheckBox;

    public ExtendedCheckBoxListView(Context context, ExtendedCheckBox aCheckBoxifiedText) {
         super(context);
         …
         mText.setFocusable(false);
         mText.setFocusableInTouchMode(false);

         mCheckBox.setFocusable(false);
         mCheckBox.setFocusableInTouchMode(false);
        …       
    }
}
Rabi
sumber
3
Saya suka solusi Anda: jika hanya ada satu widget "yang dapat diklik" per baris, menolaknya untuk fokus adalah solusi yang elegan. Ini berarti bahwa ketukan di mana saja pada baris akan cocok, tetapi itu adalah perilaku yang berguna jika widgetnya berupa radio atau kotak centang. Hal yang sama dapat dicapai dalam XML menggunakan android: focusable = "false" dan android: focusableInTouchMode = "false".
Pierre-Luc Paour
1
cara xml sepertinya tidak berhasil jika Anda mengubah visibilitas, jadi seseorang harus melakukannya melalui kode setelah menyetel "View" menjadi terlihat
max4ever
13

Saya memiliki masalah yang sama: OnListItemClick tidak dipecat! [ASK]
Itu terjadi pada kelas yang memperluas ListActivity,
dengan layout untuk ListActivity yang membuat TextBox konten dan ListView bersarang ke dalam LinearLayout
dan layout lain untuk baris (CheckBox dan TextBox bersarang ke LineraLayout).

Itu kode:

res / layout / configpage.xml (utama untuk ListActivity)

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent" > 
    <TextView  
        android:id="@+id/selection"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="pippo" /> 
    <ListView  
        android:id="@android:id/list"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:drawSelectorOnTop="false"  
        android:background="#aaFFaa" > 
    </ListView> 
<LinearLayout> 

res/layout/row.xml (layout for single row)  
<LinearLayout  
  xmlns:android="http://schemas.android.com/apk/res/android"  
  android:layout_width="fill_parent"  
  android:layout_height="wrap_content"> 
  <CheckBox  
      android:id="@+id/img"  
      android:layout_width="wrap_content"  
      android:layout_height="wrap_content"  
      **android:focusable="false"**  
      **android:focusableInTouchMode="false"** /> 

  <TextView  
      android:id="@+id/testo"  
      android:layout_width="wrap_content"  
      android:layout_height="wrap_content"  
      **android:focusable="false"**  
      **android:focusableInTouchMode="false"** /> 
</LinearLayout> 

src /.../.../ ConfigPage.java

public class ConfigPage extends ListActivity
{
    TextView selection;

    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.configpage);  
        // loaded from res/value/strings  
        String[] azioni = getResources().getStringArray(R.array.ACTIONS);  
        setListAdapter(new ArrayAdapter&lt;String&gt;(this, R.layout.row, 
                R.id.testo,   azioni));  
        selection = (TextView) findViewById(R.id.selection);  
    }       

    public void onListItemClick(ListView parent, View view, int position, long id)
    {
        selection.setText(" " + position);
    }
}

Ini mulai bekerja ketika saya menambahkan di row.xml

  • android:focusable="false"
  • android:focusableInTouchMode="false"

Saya menggunakan Eclipse 3.5.2
Android SDK 10.0.1
versi SDK min: 3

Saya harap ini membantu
... dan maaf untuk bahasa Inggris saya :(

rfellons.dll
sumber
@fellons tidak tahu kenapa, tapi itu tidak berhasil untuk saya. OnListItemClick saya tidak dipanggil.
likejudo
Sudahkah Anda menambahkan kode properti android: focusable = "false" dan android: focusableInTouchMode = "false"?
rfellons
2

tambahkan saja android:focusable="false"sebagai salah satu atribut tombol Anda

John
sumber
1

Saya mengalami masalah yang sama dengan ToggleButton. Setelah setengah hari membenturkan kepala saya ke dinding, saya akhirnya menyelesaikannya. Ini semudah membuat tampilan yang dapat difokuskan menjadi tidak dapat difokuskan, menggunakan 'android: focusable'. Anda juga harus menghindari bermain-main dengan fokusabilitas dan kemampuan diklik (saya baru saja membuat kata-kata) dari baris daftar, biarkan saja dengan nilai default.

Tentu saja, setelah tampilan yang dapat difokuskan di baris daftar tidak dapat difokuskan, pengguna yang menggunakan keyboard mungkin mengalami masalah, yah, memfokuskannya. Ini sepertinya tidak menjadi masalah, tetapi jika Anda ingin menulis 100% aplikasi tanpa cela, Anda dapat menggunakan kejadian onItemSelected untuk membuat elemen baris yang dipilih dapat difokuskan dan elemen dari baris yang dipilih sebelumnya tidak dapat difokuskan.

Konyol
sumber
Saya menggunakan pendekatan ini. Ini adalah cara paling sederhana, jika Anda bisa mengatasi masalah tidak bisa fokus pada item individu. Ini juga menjaga status drawable untuk item daftar sebagaimana mestinya, yang tidak dilakukan oleh beberapa solusi lainnya.
Jonathan S.
1
 ListView lv = getListView();
lv.setTextFilterEnabled(true);

lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
    int position, long id) {
  // When clicked, show a toast with the TextView text
  Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
      Toast.LENGTH_SHORT).show();
}
});
confucius
sumber
-1

Saya menggunakan getListAdapter (). GetItem (position) membuat instance Objek yang menyimpan nilai saya di dalam item

MyPojo myPojo = getListAdapter().getItem(position);

kemudian menggunakan metode pengambil dari myPojo itu akan memanggil nilai yang tepat di dalam item.

Mikey
sumber