Android'de ListView'i dinamik olarak güncelleme [kapalı]


159

Android'de, ListViewgösterilen öğelerin TextViewdeğere göre dinamik olarak güncellendiği kullanıcı girişine göre nasıl filtreleyebilirim ?

Ben böyle bir şey arıyorum:

-------------------------
| Text View             |
-------------------------
| List item             |
| List item             |
| List item             |
| List item             |
|                       |
|                       |
|                       |
|                       |
-------------------------

7
Yeniden açılış için aday gösterdim. Bu soruyu daha fazla sormak için metni güncelledim ve cevaplar hala geldiği için açıkça değerli bir topluluk kaynağı
Hamy

Lütfen soruyu tekrar açın. Açıkça yardımcı olur.
SilentNot

Yanıtlar:


286

İlk olarak, hem EditText hem de ListView içeren bir XML düzeni oluşturmanız gerekir.

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <!-- Pretty hint text, and maxLines -->
    <EditText android:id="@+building_list/search_box" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="type to filter"
        android:inputType="text"
        android:maxLines="1"/>

    <!-- Set height to 0, and let the weight param expand it -->
    <!-- Note the use of the default ID! This lets us use a 
         ListActivity still! -->
    <ListView android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="0dip"
        android:layout_weight="1" 
         /> 

</LinearLayout>

Bu, ListView'ın üstünde güzel bir EditText ile her şeyi düzgün bir şekilde düzenleyecektir. Ardından, normalde yaptığınız gibi bir ListActivity oluşturun, ancak son zamanlarda bildirilen mizanpajımızı kullanmamız setContentView()için onCreate()yönteme bir çağrı ekleyin . ListViewÖzel olarak kimliğimizi hatırlayın android:id="@android:id/list". Bu, bildirilen düzenimizde ListActivityhangisini ListViewkullanmak istediğimizi bilmenizi sağlar .

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

        setContentView(R.layout.filterable_listview);

        setListAdapter(new ArrayAdapter<String>(this,
                       android.R.layout.simple_list_item_1, 
                       getStringArrayList());
    }

Uygulamayı şimdi çalıştırdığınızda, ListViewyukarıdaki güzel bir kutu ile öncekinizi göstermelisiniz. Bu kutunun bir şey yapması için, girdiyi ondan almamız ve bu giriş filtresini liste haline getirmemiz gerekir. Birçok kişi bunu manuel olarak yapmaya çalışsa da, çoğu ListView Adapter sınıf Filterfiltrelemeyi otomatik olarak gerçekleştirmek için kullanılabilecek bir nesne ile birlikte gelir . Biz sadece boruya girdi ihtiyaç EditTexthaline Filter. Anlaşılan oldukça kolay. Hızlı bir test yapmak için bu satırı onCreate()aramanıza ekleyin

adapter.getFilter().filter(s);

ListAdapterBu işi yapmak için bir değişkene kaydetmeniz gerekeceğine dikkat edin - ArrayAdapter<String>daha önce 'adaptör' adı verilen bir değişkene kaydettim .

Bir sonraki adım, girdiyi EditText. Bu aslında biraz düşünüyor. Bir ekleyebilir OnKeyListener()adresinden Müşteri EditText. Ancak, bu dinleyici yalnızca bazı önemli olayları alır . Örneğin, bir kullanıcı 'wyw' girerse, tahmini metin muhtemelen 'göz' önerecektir. Kullanıcı 'wyw' veya 'eye' seçimini yapana kadar OnKeyListenerönemli bir etkinlik almazsınız. Bazıları bu çözümü tercih edebilir, ancak sinir bozucu buldum. Her önemli olayı istedim, bu yüzden filtreleme ya da filtreleme seçeneğim yoktu. Çözüm bir TextWatcher. Basitçe oluşturmak ve eklemek TextWatcheriçin EditText, ve geçiş ListAdapter Filterbir filtre isteği metin her değiştirdiğinde. Kaldırmayı unutmayın TextWatcherin OnDestroy()! İşte nihai çözüm:

private EditText filterText = null;
ArrayAdapter<String> adapter = null;

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

    setContentView(R.layout.filterable_listview);

    filterText = (EditText) findViewById(R.id.search_box);
    filterText.addTextChangedListener(filterTextWatcher);

    setListAdapter(new ArrayAdapter<String>(this,
                   android.R.layout.simple_list_item_1, 
                   getStringArrayList());
}

private TextWatcher filterTextWatcher = new TextWatcher() {

    public void afterTextChanged(Editable s) {
    }

    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
    }

    public void onTextChanged(CharSequence s, int start, int before,
            int count) {
        adapter.getFilter().filter(s);
    }

};

@Override
protected void onDestroy() {
    super.onDestroy();
    filterText.removeTextChangedListener(filterTextWatcher);
}

7
ListView filtrelemek için basit bir yolu var mı "moda" yerine "başlar" yerine bu çözüm gibi moda?
Viktor Brešan

12
Viktor - İlgilendiğiniz kelimeler boşluklarla ayrılırsa, bunu otomatik olarak yapar. Aksi halde, gerçekten değil. Muhtemelen en kolay yol, Bağdaştırıcıyı genişleterek alt sınıflamak ve tanımladığınız bir Filter nesnesini döndürmek için getFilter yöntemini geçersiz kılmaktır. Bkz github.com/android/platform_frameworks_base/blob/master/core/... kod ve değişim hatları 479 ve 486% 95'ini kopyalamak basit olurdu - nasıl varsayılan ArrayFilter işleri anlamak
Hamy

2
Hamy, mükemmel yazma! Gerçi bir sorum var: Bunu uyguladım ve yazdığım her harften sonra, ListView birkaç saniye kaybolur ve sonra geri gelir, süzülür. Bunu yaşadın mı? Sezgim, listede önemsiz olmayan toString () işlevlerine sahip 600'den fazla öğem olması.
lowellk

2
Daha küçük bir ekranda yatay modda, EditText + klavyesi tüm ekranı alır ve ListView görünmez! Herhangi bir çözüm?
Martin Konicek

4
Bu gerçekten gerekli mi? >) OnDestroy (içinde TextWatcher kaldırmayı unutmayın
Jojo

10

programın çalıştırılması kapanma kuvvetine neden olur.

Hattı değiştirdim:

android: id = "+ building_list / search_box"

ile

android: id = "@ + id / search_box"

sorun bu olabilir mi? '@ + Building_list' ne işe yarıyor?


Johe, R.id.something dediğinizde, android: id = "@ + id / search_box" dediğiniz için kimlikte bir şey var. Android: id = "@ + building_list / search_box" derseniz kodda findViewById (R.building_list.search_box); Aldığınız en üst düzey istisna nedir? Bu kod test derleme
olmadan

Merhaba Hamy, koddaki "filterText = (EditText) findViewById (R.id.search_box);" @ + building_list / search_box "; Bu yüzden merak ediyordum.
j7nn7k

1
Yazmaya başlarken zorunlu kapanır. Hatanın bir kısmı: ERROR / AndroidRuntime (188): java.lang.NullPointerException 02-11 07: 30: 29.828: ERROR / AndroidRuntime (188): xxx.com.ListFilter $ 1 adresinde. onTextChanged (ListFilter.java:46) 02-11 07: 30: 29.828: ERROR / AndroidRuntime (188): android.widget.TextView.sendOnTextChanged (TextView.java:6102) 02-11 07: 30: 29.828: HATA / AndroidRuntime (188): android.widget.TextView.handleTextChanged (TextView.java:6143) 02-11 07: 30: 29.828: ERROR / AndroidRuntime (188): android.widget.TextView $ ChangeWatcher.onTextChanged (TextView.java'da : 6286)
j7nn7k

Johe, Hata! Görünüşe göre @ + building_list'ten kurtulmak için kodu değiştirmeye çalışıyordum (çünkü bu bir karışıklık noktası) ama her yerde yakalamadım. Bahşiş için teşekkürler! Sadece + id olarak değiştirmek onu düzeltmeli
Hamy

4

filtreleme ile ilgili bir sorun vardı, sonuçlar filtrelendi, ancak geri yüklenmedi !

bu yüzden filtreleme (aktivite başlangıcı) önce bir liste yedekleme oluşturdu .. (sadece aynı verileri içeren başka bir liste)

filtrelemede, filtre ve listadapter birincil listeye bağlanır.

ancak filtrenin kendisi yedeklenen listedeki verileri kullandı.

Bu benim durumumda, listenin hemen güncellenmesini ve arama terimi karakterlerini silerken bile liste her durumda başarıyla geri yüklenmesini sağladı :)

yine de bu çözüm için teşekkürler.

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.