如何在BaseAdapter上实现getFilter?

时间:2012-07-23 20:18:00

标签: android listview filter baseadapter

我正在尝试在基础适配器上实现getFilter()以过滤List上的搜索结果。有没有关于如何实现getFilter()的示例?

MainActivity.java

   final AppInfoAdapter adapter = new AppInfoAdapter(this, Utilities.getSystemFilteredApplication(this), getPackageManager());


        public void onTextChanged(CharSequence s, int start, int before,
                int count) {
           adapter.getFilter().filter(s); //Filter from my adapter
           adapter.notifyDataSetChanged(); //Update my view
        }

AppInfoAdapter.java

package com.example.permission;

import java.util.List;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;

public class AppInfoAdapter extends BaseAdapter implements Filterable{
    private Context mContext;
    private List mListAppInfo;
    PackageManager mPackManager;

    public AppInfoAdapter(Context c, List list, PackageManager pm) {
        mContext = c;
        mListAppInfo = list;
        mPackManager = pm;
    }

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


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


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

    public View getView(int position, View convertView, ViewGroup parent) {
        // get the selected entry
        ApplicationInfo entry = (ApplicationInfo) mListAppInfo.get(position);

        // reference to convertView
        View v = convertView;

        // inflate new layout if null
        if(v == null) {
            LayoutInflater inflater = LayoutInflater.from(mContext);
            v = inflater.inflate(R.layout.layout_appinfo, null);
        }

        // load controls from layout resources
        ImageView ivAppIcon = (ImageView)v.findViewById(R.id.ivIcon);
        TextView tvAppName = (TextView)v.findViewById(R.id.tvName);
        TextView tvPkgName = (TextView)v.findViewById(R.id.tvPack);

        // set data to display
        ivAppIcon.setImageDrawable(entry.loadIcon(mPackManager));
        tvAppName.setText(entry.loadLabel(mPackManager));
        tvPkgName.setText(entry.packageName);

        // return view
        return v;
    }

    public Filter getFilter() {
        // TODO Auto-generated method stub
        return null;
    }


}

编辑:编辑代码并添加完整的AppInfoAdapter.java

7 个答案:

答案 0 :(得分:7)

适配器中的

将此类用于getfilter方法

//this is a simple class that filtering the ArrayList of strings used in adapter

public class filter_here extends Filter{

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            // TODO Auto-generated method stub

            FilterResults Result = new FilterResults();
            // if constraint is empty return the original names
            if(constraint.length() == 0 ){
                Result.values = Original_Names;
                Result.count = Original_Names.size();
                return Result;
            }

            ArrayList<String> Filtered_Names = new ArrayList<String>();
            String filterString = constraint.toString().toLowerCase();
            String filterableString;

            for(int i = 0; i<Original_Names.size(); i++){
                filterableString = Original_Names.get(i);
                if(filterableString.toLowerCase().contains(filterString)){
                    Filtered_Names.add(filterableString);
                }
            }
            Result.values = Filtered_Names;
            Result.count = Filtered_Names.size();

            return Result;
        }

        @Override
        protected void publishResults(CharSequence constraint,FilterResults results) {
            // TODO Auto-generated method stub
            Names = (ArrayList<String>) results.values;
            notifyDataSetChanged();
        }

    }

在getfilter中返回实例

@Override
    public Filter getFilter() {
        // TODO Auto-generated method stub
        return filter;
    }

full example

答案 1 :(得分:5)

这几乎让我死了:)

  1. 像这样实现您的BaseAdapter:
  2. 在公共适配器类中定义List的ArrayList,它将包含原始列表的临时项目。

    public class MyAdapter extends BaseAdapter implements Filterable{
    
        public static ArrayList<String> temporarylist;
        public static ArrayList<String> OriginalList;
        private Activity activity;
    
        public MyAdapter(Activity activity, ArrayList<String> OriginalList) {
             super();
             this.activity=activity;
             this.OriginalList = OriginalList;
             temporarylist=OriginalList;
    
        }
        .
        .
        .
    
  3. 使用以下代码[作为示例]创建getFilter()方法:

    public Filter getFilter() {
        Filter filter = new Filter() {
    
        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            temporarylist=(ArrayList<String>)results.values;
            notifyDataSetChanged();
        }
    
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();
            ArrayList<String> FilteredList= new ArrayList<String>();
            if (constraint == null || constraint.length() == 0) {
                // No filter implemented we return all the list
                results.values = OriginalList;
                results.count = OriginalList.size();
            }
            else {
                for (int i = 0; i < OriginalList.size(); i++) {
                    String data = OriginalList.get(i);
                    if (data.toLowerCase().contains(constraint.toString()))  {
                        FilteredList.add(data);
                    }
                }
                results.values = FilteredList;
                results.count = FilteredList.size();
            }
            return results;
        }
    };
    return filter;
    }
    
  4. 最后在你的EditText活动中:

    MyAdapter adapter;
    ArrayList<String> items;
    
    
    ListView list = (ListView) findViewById(R.id.list);
    items = new ArrayList<String>();
    for (int i=0;i<30;i++){
         items.add("Hello world "+String.valueof(i));
    }
    adapter = new GameAdapter(this, items);
    list.setAdapter(adapter);
    
    
    EditText inputSearch = (EditText) findViewById(R.id.Search_txt);
         inputSearch.addTextChangedListener(new TextWatcher() {
    
                @Override
                public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
                    // When user changed the Text
                    MyActivity.this.adapter.getFilter().filter(cs);
                }
    
                @Override
                public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                        int arg3) {
                    // TODO Auto-generated method stub
    
                }
    
                @Override
                public void afterTextChanged(Editable arg0) {
                    // TODO Auto-generated method stub                          
                }
            });
    

答案 2 :(得分:1)

您需要返回Filter的实例。编写过滤器,子类Filter并实现performFilteringpublishResults。请参阅docs

答案 3 :(得分:1)

你可以发布完整的AppInfoAdapter吗?也有任何理由延伸到BaseAdapter而不是ArrayAdapter?如果您有ArrayList个对象,请使用ArrayAdapter,它已经实现了Filterable接口。

实际上您使用的是List,您的适配器可以重写为ArrayAdapter已扩展Filterable

public class AppInfoAdapter extends ArrayAdapter<ApplicationInfo> {

    private Context mContext;
    PackageManager mPackManager;

    public AppInfoAdapter(Context c, List<ApplicationInfo> list, PackageManager pm) {
        super(c, 0, new ArrayList<ApplicationInfo>());
        mContext = c;
        mPackManager = pm;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // get the selected entry
        ApplicationInfo entry = (ApplicationInfo) getItem(position);

        // reference to convertView
        View v = convertView;

        // inflate new layout if null
        if(v == null) {
            LayoutInflater inflater = LayoutInflater.from(mContext);
            v = inflater.inflate(R.layout.layout_appinfo, null);
        }

        // load controls from layout resources
        ImageView ivAppIcon = (ImageView)v.findViewById(R.id.ivIcon);
        TextView tvAppName = (TextView)v.findViewById(R.id.tvName);
        TextView tvPkgName = (TextView)v.findViewById(R.id.tvPack);

        // set data to display
        ivAppIcon.setImageDrawable(entry.loadIcon(mPackManager));
        tvAppName.setText(entry.loadLabel(mPackManager));
        tvPkgName.setText(entry.packageName);

        // return view
        return v;
    }
}

答案 4 :(得分:1)

一般程序

  1. 在ListView上启用文本过滤
  2. 更改baseadapter以存储列表的两个副本,一个原件,一个已过滤。
  3. 更改BaseAdapter中的所有访问引用,以引用已过滤列表,而不是原始。
  4. 在BaseAdapter中实现过滤功能。
  5. 步骤1:
    listview.setTextFilterEnabled(true);

    第2步:

    public class AppInfoAdapter extends BaseAdapter implements Filterable{
        private List mListAppInfo;
        private List mListAppInfoFiltered;
    
    public AppInfoAdapter(Context c, List list, PackageManager pm) {
        mContext = c;
        mListAppInfo = list;
        mPackManager = pm;
        mPackManagerFiltered = pm; //added line
    }
    

    第3步:

    public int getCount() {
        return mListAppInfoFiltered.size();
    }
    public Object getItem(int position) {
        return mListAppInfoFiltered.get(position);
    }
    public View getView(int position, View convertView, ViewGroup parent) {
        // get the selected entry
        ApplicationInfo entry = (ApplicationInfo) mListAppInfoFiltered.get(position);
    

    }

    第4步: 我不确定你的列表是什么类型,所以假设一个字符串列表:

    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults results = new FilterResults();
                if (constraint == null || constraint.length() == 0) {
                    //no search, so just return all the data
                    results.count = mListAppInfo.size();
                    results.values = mListAppInfo;
                } else {//do the search
                    List<String> resultsData = new ArrayList<>();
                    String searchStr = constraint.toString().toUpperCase();
                    for (String s : mListAppInfo)
                            if (s.toUpperCase().contains(searchStr)) resultsData.add(s);
                        results.count = resultsData.size();
                        results.values = resultsData;
                    }
                    return results;
                }
    
                @Override
                protected void publishResults(CharSequence constraint, FilterResults results) {
                    mListAppInfoFiltered = (ArrayList<MyObject>) results.values;
                    notifyDataSetChanged();
                }
            };
        }
    }
    

答案 5 :(得分:0)

getFilter()可以在适配器中覆盖并返回包含已过滤列表的过滤器对象。 Filter()类有两个关键方法; 执行过滤 publishResults 。第一种方法在工作线程中执行过滤,后一种方法返回过滤的对象列表。

您可以参考下面的示例代码

@Override
public Filter getFilter() {

        return new Filter() {

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                // TODO Auto-generated method stub
                if (results.count == 0) {
                    notifyDataSetInvalidated();
                }else{
                    mListAppInfo = (ArrayList<SampleItem>) results.values;
                    notifyDataSetChanged();
                }
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                // TODO Auto-generated method stub
                FilterResults results = new FilterResults();

                if (constraint == null || constraint.length() == 0) {
                    results.values = mListAppInfo;
                    results.count = mListAppInfo.size();
                }else{
                    ArrayList<SampleItem> filter_items = new ArrayList<>(); 
                    for (SampleItem item : mListAppInfo) {
                        if (item.getItemName().toLowerCase().startsWith(constraint.toString().toLowerCase())) {
                            filter_items.add(item);
                        }
                    }
                    results.values =  filter_items ;
                    results.count = filter_items.size();
                }
                return results;
            }
        };
    }

希望你觉得它很有用。

答案 6 :(得分:-1)

使用ArrayAdapter扩展您的类,然后重写方法,并创建过滤器类的对象并随之返回。