Android पर ListView को गतिशील रूप से कैसे अपडेट करें [बंद]


159

एंड्रॉइड पर, मैं ListViewउपयोगकर्ता इनपुट के आधार पर फ़िल्टर कैसे कर सकता हूं , जहां दिखाए गए आइटम गतिशील रूप से TextViewमूल्य के आधार पर अपडेट किए जाते हैं ?

मैं कुछ इस तरह की तलाश में हूँ:

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

7
मैं फिर से खोलने के लिए नामांकित करता हूं। मैंने इस प्रश्न को और अधिक बनाने के लिए पाठ को अद्यतन किया है, और यह स्पष्ट रूप से एक मूल्यवान सामुदायिक संसाधन है क्योंकि उत्तर अभी भी आ रहे हैं
Hamy

कृपया प्रश्न पुनः खोलें। यह स्पष्ट रूप से सहायक है।
साइलेंटनॉट

जवाबों:


286

सबसे पहले, आपको एक XML लेआउट बनाने की आवश्यकता है जिसमें एक EditText और एक ListView दोनों हैं।

<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>

यह सब कुछ ठीक से बाहर कर देगा, ListView के ऊपर एक अच्छा EditText के साथ। इसके बाद, सामान्य रूप से एक ListActivity बनाएं, लेकिन विधि setContentView()में एक कॉल जोड़ें onCreate()ताकि हम अपने हाल ही में घोषित लेआउट का उपयोग करें। याद रखें कि हमने ListViewविशेष रूप से ID'ed किया है android:id="@android:id/list"। यह ListActivityजानने की अनुमति देता है कि ListViewहम अपने घोषित लेआउट में किसका उपयोग करना चाहते हैं।

    @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());
    }

ऐप को चलाना अब अपने पिछले को दिखाना चाहिए ListView, ऊपर एक अच्छे बॉक्स के साथ। उस बॉक्स को कुछ करने के लिए, हमें उससे इनपुट लेना होगा, और उस इनपुट को सूची को फ़िल्टर करना होगा। जबकि बहुत से लोगों ने मैन्युअल रूप से ऐसा करने की कोशिश की है, ज्यादातर ListView Adapter कक्षाएं एक Filterऑब्जेक्ट के साथ आती हैं जिसका उपयोग स्वचालित रूप से फ़िल्टर करने के लिए किया जा सकता है। हमें बस इनपुट को अंदर से पाइप करना EditTextहोगा Filter। पता चला कि यह बहुत आसान है। एक त्वरित परीक्षण चलाने के लिए, इस लाइन को अपने onCreate()कॉल में जोड़ें

adapter.getFilter().filter(s);

ध्यान दें कि ListAdapterइस काम को करने के लिए आपको अपने एक वैरिएबल को सहेजना होगा - मैंने अपने ArrayAdapter<String>पहले से 'एडेप्टर' नामक वैरिएबल में सेव कर लिया है ।

अगला कदम इनपुट से प्राप्त करना है EditText। यह वास्तव में एक सा लगता है। आप OnKeyListener()अपने को जोड़ सकते हैं EditText। हालाँकि, यह श्रोता केवल कुछ प्रमुख घटनाओं को प्राप्त करता है । उदाहरण के लिए, यदि कोई उपयोगकर्ता 'wyw' में प्रवेश करता है, तो भविष्य कहनेवाला पाठ 'आंख' की सिफारिश करेगा। जब तक उपयोगकर्ता या तो 'wyw' या 'eye' चुनता है, तब तक आपको OnKeyListenerएक महत्वपूर्ण ईवेंट प्राप्त नहीं होगा। कुछ इस समाधान को पसंद कर सकते हैं, लेकिन मैंने इसे निराशाजनक पाया। मैं हर महत्वपूर्ण घटना चाहता था, इसलिए मेरे पास फ़िल्टरिंग या फ़िल्टरिंग नहीं करने का विकल्प था। समाधान एक है TextWatcher। बस हर बार टेक्स्ट में बदलाव TextWatcherकरने और जोड़ने के EditTextलिए ListAdapter Filterएक फ़िल्टर अनुरोध करें और पास करें । दूर करने के लिए याद रखें TextWatcherमें OnDestroy()! यहाँ अंतिम समाधान है:

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
क्या सूची में फ़िल्टर करने का कोई सीधा तरीका "समाहित है" के बजाय "शुरू होता है" फैशन के साथ "जैसे समाधान करता है?"
विक्टर ब्रिज़न

12
विक्टर - यदि आप जिन शब्दों में रुचि रखते हैं, उन्हें रिक्त स्थान द्वारा अलग किया जाता है, तो यह स्वचालित रूप से ऐसा करेगा। अन्यथा, वास्तव में नहीं। संभवत: सबसे आसान तरीका एडेप्टर को इसे बढ़ाकर उप-वर्ग करना होगा, और फ़िल्टर ऑब्जेक्ट को परिभाषित करने के लिए getFilter विधि को ओवरराइड करें। देखें github.com/android/platform_frameworks_base/blob/master/core/... इस कोड और परिवर्तन लाइनों 479 और 486 के 95% की नकल करने के लिए सरल हो सकता है - समझने के लिए डिफ़ॉल्ट ArrayFilter काम करता है
Hamy

2
हमी, बेहतरीन राइटअप! हालांकि मेरे पास एक सवाल है: मैंने इसे लागू किया है और प्रत्येक पत्र के बाद जो मैं टाइप करता हूं, ListView कुछ सेकंड के लिए गायब हो जाता है और फिर वापस आता है, फ़िल्टर किया जाता है। क्या आपने इसका अनुभव किया है? मेरा अंतर्ज्ञान यह है कि यह इसलिए है क्योंकि मेरे पास सूची में 600+ आइटम हैं, गैर-तुच्छ स्टर्लिंग () फ़ंक्शन के साथ।
लोवेलक

2
छोटी स्क्रीन पर लैंडस्केप मोड में, EditText + कीबोर्ड पूरी स्क्रीन लेता है और ListView दिखाई नहीं देता है! कोई भी समाधान?
मार्टिन कोनिसक

4
क्या यह वास्तव में आवश्यक है? > ऑनडेस्ट्रो () में टेक्स्टवॉकर को हटाने के लिए याद रखें
जोजो

10

प्रोग्राम चलाने से एक बल पास होगा।

मैंने लाइन स्वैप की:

एंड्रॉयड: आईडी = "@ + building_list / search_box"

साथ में

एंड्रॉयड: आईडी = "@ + id / search_box"

क्या यह समस्या हो सकती है? '@ + बिल्डिंग_लिस्ट ’किसके लिए है?


जोह, जब आप R.id.something कहते हैं, तो कुछ आईडी में मौजूद होता है क्योंकि आपने Android: id = "@ + id / search_box" कहा है। अगर आप android: id = "@ + building_list / search_box" कहते हैं तो कोड में आप findViewById (R.building_list.search_box) को कॉल कर सकते हैं; शीर्ष स्तर का अपवाद आपको क्या मिल रहा है? इस कोड को w / oa परीक्षा संकलन में कॉपी किया गया है, इसलिए मुझे संभावना है कि कम से कम एक त्रुटि कहीं न कहीं
Hamy

हाय हमी, आपने "filterText = (EditText) findViewById (R.id.search_box)" के साथ कोड में "@ + भवन_सूची / खोज_बॉक्स" संदर्भित किया; इसलिए मैं सोच रहा था।
j7nn7k

1
जब टाइप करने के लिए शुरू होता है तो संदंश का कवच। त्रुटि का हिस्सा: ERROR / AndroidRuntime (188): java.lang.NullPointerException 02-11 07: 30: 29.828: ERROR (AndroidRuntime (188): xxx.com.ListFilter $ 1 पर। 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: ERROR / 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) पर : 6286)
j7nn7k

जोह, ऊप्स - ऐसा लगता है कि मैं @ + बिल्डिंग_लिस्ट से छुटकारा पाने के लिए कोड को संशोधित करने की कोशिश कर रहा था (क्योंकि यह भ्रम की स्थिति है) लेकिन मैंने इसे हर जगह नहीं पकड़ा। पारितोषिक के लिए धन्यवाद! बस इसे बदलने के लिए @ + आईडी को इसे ठीक करना चाहिए
हेमी

4

मुझे फ़िल्टर करने में समस्या थी, जिसके परिणाम फ़िल्टर किए गए हैं, लेकिन बहाल नहीं किए गए हैं !

इसलिए फ़िल्टर करने से पहले (गतिविधि शुरू) मैंने एक सूची बैकअप बनाया (बस एक और सूची, जिसमें एक ही डेटा है)

फ़िल्टर करने पर, फ़िल्टर और सूचीकर्ता प्राथमिक सूची से जुड़ा होता है।

लेकिन फ़िल्टर ने ही बैकअप सूची से डेटा का उपयोग किया।

मेरे मामले में यह सुनिश्चित हो गया, कि सूची को तुरंत अपडेट कर दिया गया था और यहां तक ​​कि खोज-अवधि-वर्णों को हटाने पर भी सूची हर बार सफलतापूर्वक पुनर्प्राप्त हो जाती है :)

वैसे भी इस समाधान के लिए धन्यवाद।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.