سؤال

على نظام Android، كيف يمكنني ListView التي تقوم بالتصفية بناءً على إدخال المستخدم، حيث يتم تحديث العناصر المعروضة ديناميكيًا بناءً على TextView قيمة؟

أنا أبحث عن شيء مثل هذا:

-------------------------
| Text View             |
-------------------------
| List item             |
| List item             |
| List item             |
| List item             |
|                       |
|                       |
|                       |
|                       |
-------------------------
هل كانت مفيدة؟

المحلول

أولا، تحتاج إلى إنشاء تخطيط 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>

وهذا سيضع كل شيء بشكل صحيح، مع EDITTEXT لطيفة فوق يكون ListView. بعد ذلك، إنشاء ListActivity كما تفعل عادة، ولكن إضافة مكالمة setContentView() في طريقة onCreate() لذلك نحن نستخدم تخطيط أعلن مؤخرا. نتذكر أننا ID'ed وListView خصيصا، مع 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 "أو" العين "، و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);
}

نصائح أخرى

وتشغيل البرنامج للسيسبب قريب القوة.

وأنا swaped السطر:

<اقتباس فقرة>   

والروبوت: معرف = "@ + building_list / search_box"

مع

<اقتباس فقرة>   

والروبوت: معرف = "@ + معرف / search_box"

ويمكن أن تكون المشكلة؟ ما هو '@ + building_list "ل؟

واجهت مشكلة في التصفية ، وقد تم تصفية النتائج ، ولكن لم يتم استعادتها!

لذلك قبل التصفية (بدء النشاط) قمت بإنشاء نسخة احتياطية للقائمة..(مجرد قائمة أخرى تحتوي على نفس البيانات)

عند التصفية، يتم توصيل المرشح ومحول القائمة بالقائمة الأساسية.

لكن الفلتر نفسه استخدم البيانات من القائمة المنسوخة احتياطيًا.

وهذا يضمن في حالتي أنه تم تحديث القائمة على الفور وحتى عند حذف أحرف مصطلح البحث، يتم استعادة القائمة بنجاح في كل حالة :)

شكرا لهذا الحل على أي حال.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top