Android'deki öğelerde Özel ListView tıklama sorunu


110

Bu yüzden özel bir ListView nesnem var. Liste öğelerinin üst üste yığılmış iki metin görünümü ve gerçekten bir şey yapana kadar gizli kalmasını istediğim yatay bir ilerleme çubuğu vardır. En sağda, yalnızca kullanıcının güncellemeleri veritabanlarına indirmesi gerektiğinde görüntülemek istediğim bir onay kutusu var. Görünürlüğü Visibility.GONE olarak ayarlayarak onay kutusunu devre dışı bıraktığımda, liste öğelerine tıklayabiliyorum. Onay kutusu göründüğünde, listedeki onay kutuları dışında hiçbir şeyi tıklayamıyorum. Biraz araştırma yaptım ama mevcut durumumla alakalı hiçbir şey bulamadım. Bu soruyu buldumancak dahili olarak veritabanları listesini içermek için ArrayLists kullandığım için geçersiz kılınmış bir ArrayAdapter kullanıyorum. Sadece LinearLayout görünümünü alıp Tom'un yaptığı gibi bir onClickListener eklemem gerekiyor mu? Emin değilim.

Liste görünümü satır düzeni XML'si şöyledir:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:padding="6dip">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="0dip"
        android:layout_weight="1"
        android:layout_height="fill_parent">
        <TextView
            android:id="@+id/UpdateNameText"
            android:layout_width="wrap_content"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:textSize="18sp"
            android:gravity="center_vertical"
            />
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:id="@+id/UpdateStatusText"
            android:singleLine="true"
            android:ellipsize="marquee"
            />
        <ProgressBar android:id="@+id/UpdateProgress" 
                     android:layout_width="fill_parent" 
                     android:layout_height="wrap_content"
                     android:indeterminateOnly="false" 
                     android:progressDrawable="@android:drawable/progress_horizontal" 
                     android:indeterminateDrawable="@android:drawable/progress_indeterminate_horizontal" 
                     android:minHeight="10dip" 
                     android:maxHeight="10dip"                    
                     />
    </LinearLayout>
    <CheckBox android:text="" 
              android:id="@+id/UpdateCheckBox" 
              android:layout_width="wrap_content" 
              android:layout_height="wrap_content" 
              />
</LinearLayout>

Ve işte ListActivity'yi genişleten sınıf. Açıkçası hala geliştirme aşamasında, bu yüzden eksik olan veya etrafta bırakılmış olabilecek şeyleri affedin:

public class UpdateActivity extends ListActivity {

    AccountManager lookupDb;
    boolean allSelected;
    UpdateListAdapter list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        lookupDb = new AccountManager(this);
        lookupDb.loadUpdates();

        setContentView(R.layout.update);
        allSelected = false;

        list = new UpdateListAdapter(this, R.layout.update_row, lookupDb.getUpdateItems());
        setListAdapter(list);

        Button btnEnterRegCode = (Button)findViewById(R.id.btnUpdateRegister);
        btnEnterRegCode.setVisibility(View.GONE);

        Button btnSelectAll = (Button)findViewById(R.id.btnSelectAll);
        btnSelectAll.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
                allSelected = !allSelected;

                for(int i=0; i < lookupDb.getUpdateItems().size(); i++) {
                    lookupDb.getUpdateItem(i).setSelected(!lookupDb.getUpdateItem(i).isSelected());
                }

                list.notifyDataSetChanged();
                // loop through each UpdateItem and set the selected attribute to the inverse 

            } // end onClick
        }); // end setOnClickListener

        Button btnUpdate = (Button)findViewById(R.id.btnUpdate);
        btnUpdate.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
            } // end onClick
        }); // end setOnClickListener

        lookupDb.close();
    } // end onCreate


    @Override
    protected void onDestroy() {
        super.onDestroy();

        for (UpdateItem item : lookupDb.getUpdateItems()) {
            item.getDatabase().close();        
        }
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);

        UpdateItem item = lookupDb.getUpdateItem(position);

        if (item != null) {
            item.setSelected(!item.isSelected());
            list.notifyDataSetChanged();
        }
    }

    private class UpdateListAdapter extends ArrayAdapter<UpdateItem> {
        private List<UpdateItem> items;

        public UpdateListAdapter(Context context, int textViewResourceId, List<UpdateItem> items) {
            super(context, textViewResourceId, items);
            this.items = items;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View row = null;

            if (convertView == null) {
                LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                row = li.inflate(R.layout.update_row, null);
            } else {
                row = convertView;
            }

            UpdateItem item = items.get(position);

            if (item != null) {
                TextView upper = (TextView)row.findViewById(R.id.UpdateNameText);
                TextView lower = (TextView)row.findViewById(R.id.UpdateStatusText);
                CheckBox cb = (CheckBox)row.findViewById(R.id.UpdateCheckBox);

                upper.setText(item.getName());
                lower.setText(item.getStatusText());

                if (item.getStatusCode() == UpdateItem.UP_TO_DATE) {
                    cb.setVisibility(View.GONE);
                } else {
                    cb.setVisibility(View.VISIBLE);
                    cb.setChecked(item.isSelected());
                }

                ProgressBar pb = (ProgressBar)row.findViewById(R.id.UpdateProgress);
                pb.setVisibility(View.GONE);
            }
            return row;
        }

    } // end inner class UpdateListAdapter
}

düzenleme: Hala bu sorunu yaşıyorum. Hile yapıyorum ve metin görünümlerine onClick işleyicileri ekliyorum ancak onay kutuma tıklamadığımda onListItemClick () işlevimin hiç çağrılmaması son derece aptalca görünüyor.

Yanıtlar:


243

Sorun, Android'in üzerinde odaklanılabilen öğeler içeren liste öğelerini seçmenize izin vermemesidir. Liste öğesindeki onay kutusunu şöyle bir özniteliğe sahip olacak şekilde değiştirdim:

android:focusable="false"

Şimdi, onay kutuları içeren liste öğelerim (düğmeler için de geçerlidir) geleneksel anlamda "seçilebilir" (yanarlar, liste öğesinin herhangi bir yerine tıklayabilirsiniz ve "onListItemClick" işleyicisi ateşlenecektir, vb.).

DÜZENLEME: Güncelleme olarak bir yorumcu, "Düğmenin görünürlüğünü değiştirdikten sonra odağı programlı olarak tekrar devre dışı bırakmak zorunda kaldım" dedi.


24
Liste öğesinde ImageButton kullanıldığında bu çözüm çalışmıyor. :(
Julian A.

1
Tamam ama ya onay kutumun ve liste görünümümün birbirini dışlamasını istiyorsam? ListView Öğesini seçersem, onay kutusunu mutlaka kontrol etmek istemiyorum. Bu, bu çözümle mümkün mü?
Mike6679

@Mike Evet, bu çözüm hala etkileşimde bulunabilmek için onay kutusunun açıkça tıklanmasını gerektiriyor. Liste öğesi düzeninizde odaklanabilir öğeleriniz olduğunda, ListView'de gizemli bir şekilde atlanan işlevselliği yeniden etkinleştirir.
MattC

2
Harika cevap, teşekkürler, ImageButtons ile de iyi çalışıyor. Sadece bir not, düğmenin görünürlüğünü değiştirdikten sonra odağı programlı olarak tekrar devre dışı bırakmak zorunda kaldım.
Ljdawson

1
android: clickable = "false" ayarlamanız da gerekebilir
Mina Samy

43

Liste öğesinin içinde ImageButton varsa descendantFocusability, kök liste öğesi öğesindeki değeri "BlocksDescendants" olarak ayarlamalısınız .

android:descendantFocusability="blocksDescendants"

Ve focusableInTouchModehiç bayrak trueiçinde ImageButtongörünüme.

android:focusableInTouchMode="true"

1
Bu, görüntü düğmelerine sahip liste öğesi için mükemmel çalışır. Ama bu ImageButton dışında işe yarayabilir
raksja

12

Benzer bir sorunla karşılaştım ve CheckBox'ın ListView'da oldukça titiz olduğunu gördüm. Ne olur, iradesini tüm ListItem'e empoze eder ve onListItemClick'i bir nevi geçersiz kılar. Bunun için bir tıklama işleyicisi uygulamak ve TextViews kullanmak yerine CheckBox için text özelliğini de ayarlamak isteyebilirsiniz.

Bu View nesnesine de bakmanızı söyleyebilirim, CheckBox'tan daha iyi çalışabilir

Kontrol Edilmiş Metin Görünümü


6
Listedeki odaklanılabilir öğeler için "odaklanabilir" ayarını yanlış olarak ayarlarsanız, onListItemClick işlevinizi tekrar kullanabileceğinizi buldum.
MattC

2
Ancak onay kutusu, liste öğesi gibi turuncuya döner. Bir çözüm bilen var mı?
erdomester

8

bu satırı liste öğesinin kök görünümünde kullanın

android: descendantFocusability = "blocksDescendants"

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.