【问题标题】:ListView search widget filterListView 搜索小部件过滤器
【发布时间】:2014-12-23 14:09:33
【问题描述】:

我很难找到这方面的好教程。我有一个 ListView,我想为其添加一个“搜索”功能,该功能将根据用户在操作栏中找到的搜索小部件中的输入过滤列表视图。

我浏览了一些教程和几篇文章,但无法理解这个概念。我最近的努力是根据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 的各个行并不复杂,只有两个 textView,如下所示

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

有人可以帮帮我吗?感谢您的宝贵时间。

【问题讨论】:

  • 您是否调试过任何循环以了解这些数组是否被填充?你的 getItem 和 add 方法在哪里?此外,我相信您可能会翻转您的 notifyDataSetChanged 和 notifyDataSetInvalidated 调用,应在为适配器设置数据后调用更改

标签: android listview search android-listview filter


【解决方案1】:
  1. 您链接的那个网站已有 3 年历史,完全不正确,是一个可怕的例子。忘记它甚至存在。
  2. 如果您需要自定义实现过滤逻辑,切勿扩展ArrayAdapter。尝试执行此操作时会遇到各种问题。包括同步问题、无法使您的列表和内部适配器的列表保持同步等。进一步阅读:Filtering Problems

当您需要自定义过滤解决方案时,有两种选择。

  1. 从头开始编写您自己的适配器...例如扩展BaseAdapter
  2. 使用第 3 方库。 This one 专为满足您的要求而设计。

【讨论】:

    【解决方案2】:

    一位朋友帮忙完成了这个功能。以下是设置过滤器的重要sn-p:

    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 找到。谢谢大家的回复。

    【讨论】:

      【解决方案3】:

      也许对你有帮助,

      在片段中

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

      在适配器类中

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

      【讨论】:

        猜你喜欢
        • 2018-09-24
        • 2013-02-10
        • 2018-11-07
        • 2014-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-22
        • 2014-09-08
        相关资源
        最近更新 更多