【问题标题】:How to implement getFilter on a BaseAdapter?如何在 BaseAdapter 上实现 getFilter?
【发布时间】:2012-07-22 02:56:05
【问题描述】:

我正在尝试在基本适配器上实现 getFilter() 以过滤掉列表上的搜索结果。有没有如何实现 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

【问题讨论】:

    标签: android listview filter baseadapter


    【解决方案1】:

    在你的适配器中放入这个类以在 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

    【讨论】:

      【解决方案2】:

      这差点让我死了:)

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

      最后在您的 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                          
                  }
              });
      

      【讨论】:

        【解决方案3】:

        你能发布你的完整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;
            }
        }
        

        【讨论】:

        • 我编辑了答案,所以你的适配器extends Filterable ArrayAdapter
        • 您的代码没有错误,但现在我看不到已安装应用程序的列表,只有 EditText
        • super(c, 0, new ArrayList&lt;ApplicationInfo&gt;());换成super(c, 0, list);是我的错。
        • 搜索部分工作,无法真正理解它是如何工作的,现在它有点错误,到目前为止它只适用于关键字'android'
        • 查看ArrayAdapter 来源以了解ArrayFilter 的工作原理github.com/android/platform_frameworks_base/blob/master/core/… 或者这也可能有助于stackoverflow.com/a/4027085/1300995
        【解决方案4】:

        您需要返回一个Filter 的实例。要编写过滤器,请继承 Filter 并实现 performFilteringpublishResults。请参阅docs

        【讨论】:

          【解决方案5】:

          一般程序

          1. 在您的 ListView 上启用文本过滤
          2. 更改您的 baseadapter 以存储列表的 两份 副本,一份原件,一份过滤。
          3. 将 BaseAdapter 中的所有访问引用更改为引用过滤列表,而不是原始列表。
          4. 在 BaseAdapter 中实现您的过滤器功能。

          第 1 步:
          listview.setTextFilterEnabled(true);

          第二步:

          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
          }
          

          第三步:

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

          【讨论】:

            【解决方案6】:

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

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

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

            希望你觉得它有用。

            【讨论】:

              【解决方案7】:

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2023-03-12
                • 1970-01-01
                • 1970-01-01
                • 2012-09-09
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多