ListView搜索小部件过滤器

时间:2014-12-23 14:09:33

标签: android listview search android-listview filter

我无法为此找到好的教程。我有一个ListView,我想添加一个' search'根据操作栏中搜索小部件中的用户输入过滤列表视图的功能。

我已经浏览了几篇教程和几篇文章,但我无法理解这个概念。我最近的努力来自this site

以下是我的自定义适配器代码(请注意,由于我尝试使其运行,可能会有不必要的代码:

package adapters;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;

import com.example.khalid.hisnulmuslim.R;

import java.util.ArrayList;
import java.util.List;

import classes.Dua;

public class DuaGroupAdapter extends ArrayAdapter<Dua> implements Filterable {

    /* Filterable things */
    private List<Dua> allModelItemsArray;
    private List<Dua> filteredModelItemsArray;
    private Activity context;
    private ModelFilter filter;
    private LayoutInflater inflator;

    public DuaGroupAdapter(Activity context, List<Dua> list) {
        super(context, R.layout.dua_list_item_card, list);
        this.context = context;
        this.allModelItemsArray = new ArrayList<Dua>();
        allModelItemsArray.addAll(list);
        this.filteredModelItemsArray = new ArrayList<Dua>();
        filteredModelItemsArray.addAll(allModelItemsArray);
        inflator = context.getLayoutInflater();
        getFilter();
    }
    /* End of Filterable things */

    public DuaGroupAdapter(Context context, int textViewResourceId) {
        super(context, textViewResourceId);
    }

    public DuaGroupAdapter(Context context, int resource, List<Dua> items) {
        super(context, resource, items);
    }

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

        if (v == null) {
            LayoutInflater vi;
            vi = LayoutInflater.from(getContext());
            v = vi.inflate(R.layout.dua_list_item_card, null);
        }

        Dua p = getItem(position);

        if (p != null) {
            TextView tvReference = (TextView) v.findViewById(R.id.txtReference);
            TextView tvDuaName = (TextView) v.findViewById(R.id.txtDuaName);

            if (tvReference != null) {
                tvReference.setText("" + p.getReference());
            }
            if (tvDuaName != null) {
                tvDuaName.setText(p.getTitle());
            }
        }
        return v;
    }

    private class ModelFilter extends Filter {

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {

            constraint = constraint.toString().toLowerCase();
            FilterResults result = new FilterResults();
            if (constraint != null && constraint.toString().length() > 0) {
                ArrayList<Dua> filteredItems = new ArrayList<Dua>();

                for (int i = 0, l = allModelItemsArray.size(); i < l; i++) {
                    Dua m = allModelItemsArray.get(i);
                    if (m.getGroup().toLowerCase().contains(constraint))
                        filteredItems.add(m);
                }
                result.count = filteredItems.size();
                result.values = filteredItems;
            } else {
                synchronized (this) {
                    result.values = allModelItemsArray;
                    result.count = allModelItemsArray.size();
                }
            }
            return result;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {

            filteredModelItemsArray = (ArrayList<Dua>) results.values;
            notifyDataSetChanged();
            clear();
            for (int i = 0, l = filteredModelItemsArray.size(); i < l; i++)
                add(filteredModelItemsArray.get(i));
            notifyDataSetInvalidated();
        }
    }
}

这是我的布局XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ListView
        android:id="@+id/duaListView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:background="@android:color/white"/>
</RelativeLayout>

过滤器所需的文本将从操作栏的“搜索”小组件中获取。该活动能够检测何时将文本输入到搜索小部件文本字段中,但它什么都不显示; listView出现空白,一旦删除所有文本,它就会回到原始状态。

ListView的各行并不复杂,只有两个textViews,如下所示

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:padding="15dp"
    android:background="?android:attr/selectableItemBackground">

    <TextView
        android:id="@+id/txtReference"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="sans-serif-condensed"
        android:text="1"
        android:textStyle="bold" />

    <View
        android:layout_width="15dp"
        android:layout_height="fill_parent" />

    <TextView
        android:id="@+id/txtDuaName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="sans-serif-light"
        android:text="Entering the Bathroom" />
</LinearLayout>

有人可以帮帮我吗?谢谢你的时间。

3 个答案:

答案 0 :(得分:0)

  1. 您关联的网站是3年,完全不正确,并且是一个可怕的例子。忘记它甚至存在。
  2. 如果您需要自定义实现其过滤逻辑,请不要扩展ArrayAdapter。尝试这样做有各种各样的问题。要包含同步问题,无法保持列表和内部适配器列表同步等。有关详细信息,请参阅:Filtering Problems
  3. 当您需要自定义过滤解决方案时,有两种选择。

    1. 从头开始编写自己的适配器...例如,扩展BaseAdapter
    2. 使用第三方库。 This one尤其旨在满足您的要求。

答案 1 :(得分:0)

它可能对你有帮助,

片段中的

searchView.setOnQueryTextListener(new OnQueryTextListener()
{ 
    @Override
    public boolean onQueryTextSubmit(String query)
    { 
        return false;
    }

    @Override
    public boolean onQueryTextChange(String newText) 
    {
        mSearchStr = newText;
        if(mSearchStr.isEmpty())
        {
            mContList = new ArrayList<HashMap<String, String>>();
            FetchContacts(); 
        }
        else if(mSearchStr.length()>=1)
        {
            mMyListAdapter.getFilter().filter(mSearchStr.toString()); 
        } 
        return true;
    } 
}); 

在adapter.class中

package com.example.samplephonecontact;

    import java.util.ArrayList;  
    import java.util.HashMap;    
    import com.example.samplephonecontact.ContactListFragment; 
    import android.annotation.SuppressLint;
    import android.content.Context;  
    import android.graphics.Bitmap;  
    import android.view.LayoutInflater;
    import android.view.View; 
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;  
    import android.widget.Filter; 
    import android.widget.Filterable;
    import android.widget.ImageView;
    import android.widget.TextView;  

    public class ContactListAdapter extends BaseAdapter  implements Filterable
    { 
        private Context mContext;
        private ValueFilter mValueFilter; 
        ArrayList<HashMap<String, String>> mContList;
        ArrayList<HashMap<String, String>> mFilteredContList; 
        HashMap<String, String> mContObj ; 

        public ContactListAdapter(Context context, ArrayList<HashMap<String, String>> PackageList)
        {
                this.mContext = context;
                this.mContList = PackageList;
                this.mFilteredContList = PackageList; 
        }

        public int getCount()
        {
            return mContList.size();
        }

        public Object getItem(int position)
        {
            return mContList.get(position);
        }

        public long getItemId(int position)
        {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup viewGroup)
        {    
            LayoutInflater mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = mInflater.inflate(R.layout.cont_list, null);

            TextView contactName = (TextView) convertView.findViewById(R.id.name); 
            TextView contactNumber = (TextView) convertView.findViewById(R.id.number); 
            ImageView contactImage = (ImageView) convertView.findViewById(R.id.contactimage);
            mContObj = new HashMap<String, String>();
            mContObj = mContList.get(position);  
            String name = mContObj.get("name");
            String number = mContObj.get("number");  
            contactName.setText(name);  
            contactNumber.setText("\t"+number);

            int resid = R.drawable.person1; 
            contactImage.setImageResource(resid);

            return convertView;
        } 
        @Override
        public Filter getFilter() 
        {
             if(mValueFilter==null)
             {
                 mValueFilter=new ValueFilter();
             } 
                return mValueFilter;
        } 

        private class ValueFilter extends Filter
        { 
            @SuppressLint("DefaultLocale")
            @Override
            protected FilterResults performFiltering(CharSequence constraint)
            { 
                FilterResults results=new FilterResults();
                ArrayList<HashMap<String, String>> filterList=new ArrayList<HashMap<String,String>>(); 
                if(constraint!=null && constraint.length()>0)
                { 
                    for(int i=0;i<mFilteredContList.size();i++)
                    {
                        if((mFilteredContList.get(i).get("name").toString().toUpperCase()).contains(constraint.toString().toUpperCase()))
                        { 
                            String name = mFilteredContList.get(i).get("name");
                            String num = mFilteredContList.get(i).get("number");
                            String id= mFilteredContList.get(i).get("id");
                            String numType = mFilteredContList.get(i).get("number_type");
                            String mail = mFilteredContList.get(i).get("mail");
                            String mailtype = mFilteredContList.get(i).get("mail_type");
                            String ch = constraint.toString().toUpperCase();
                            if(name.toUpperCase().contains(ch))
                            { 
                                HashMap<String, String>  list = new HashMap<String, String>(); 
                                list.put("id", id);
                                list.put("name", name);
                                list.put("number", num);
                                list.put("number_type", numType);
                                list.put("mail", mail);
                                list.put("mail_type", mailtype);
                                filterList.add(list);
                            } 
                        }
                    } 
                    results.count=filterList.size();
                    results.values=filterList;
                    ArrayItem ai = new ArrayItem();
                    ai.setMyArrayList(filterList);
                }
                else
                {
                    results.count=mFilteredContList.size();
                    results.values=mFilteredContList;
                } 
                return results;
            } 

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) 
            { 
                mContList=(ArrayList<HashMap<String,String>>) results.values; 
                notifyDataSetChanged();
            }
        }
    }

答案 2 :(得分:0)

一位朋友帮忙解决了这个问题。以下是设置过滤器的重要代码段:

public class DuaGroupAdapter extends BaseAdapter implements Filterable {
    private Context mContext;
    private LayoutInflater mInflater;
    private List<Dua> mList;    

    @Override
    public Filter getFilter() {
        // return a filter that filters data based on a constraint
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                final ExternalDbOpenHelper helper = ExternalDbOpenHelper.getInstance(mContext);
                final SQLiteDatabase db = helper.openDataBase();

                final List<Dua> duas = new ArrayList<>();
                Cursor c = null;
                try {
                    c = db.query(HisnDatabaseInfo.DuaGroupTable.TABLE_NAME, null,
                            HisnDatabaseInfo.DuaGroupTable.ENGLISH_TITLE + " like ?",
                            new String[] { "%" + constraint + "%" }, null, null, null);
                    if (c != null && c.moveToFirst()) {
                        do {
                            final Dua dua = new Dua(c.getInt(0), c.getString(2));
                            duas.add(dua);
                        } while (c.moveToNext());
                    }
                } finally {
                    if (c != null) {
                        c.close();
                    }
                }

                final FilterResults results = new FilterResults();
                results.values = duas;
                results.count = duas.size();
                return results;
            }

            @Override
            protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
                if (results.count > 0) {
                    mList = (List<Dua>) results.values;
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }
        };
    }

可以找到适配器的完整代码here。感谢所有的回复。