【问题标题】:SearchView filter ListView搜索视图过滤器列表视图
【发布时间】:2014-01-10 20:31:20
【问题描述】:

我一直在尝试使用 mSearch EditText 过滤/搜索 Adapter 适配器。我正在寻求实现 getFilter() 等方面的帮助。

此活动当前正在显示内容列表。 mSearch 位于列表上方,我想在有人键入时过滤/更新列表。

如果您需要特定的代码或了解更多信息,请告诉我。提前谢谢!

public class MainActivity extends FragmentActivity {

 private SearchView mSearch;
 private List<Model> mMain = new ArrayList<Model>();

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
 }

 public class MainFragment extends Fragment implements SearchView.OnQueryTextListener {

  private ListView mListView;
  private Adapter mAdapter;

  public boolean onQueryTextChange(String query) {
   if (mAdapter != null) {
    mAdapter.getFilter().filter(query.toString());
   }
   return false;
  }

  public boolean onQueryTextSubmit(String query) {
   onQueryTextChange(query);
   return false;
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   View rootView = inflater.inflate(R.layout.main_user_list_row, container, false);

    mListView = (ListView) findViewById(R.id.listView);
    mAdapter = new Adapter();
    mListView.setAdapter(mAdapter);
    mListView.setAdapter.setTextFilterEnabled(true);

    mSearch.setOnQueryTextListener((SearchView.OnQueryTextListener) mContext);

   return rootView;

  }

  public class Adapter extends BaseAdapter implements Filterable {

   @Override
   public int getCount() {
    return mMain.size();
   }

   @Override
   public Object getItem(int position) {
    return 1;
   }

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

   @Override
   public View getView(int position, View convertView, ViewGroup parent) {
    View view = View.inflate(mContext, R.layout.main_user_list_row, null);

     if (mContext != null && mMain.get(position) != null) {
      TextView mPosition = (TextView) view.findViewById(R.id.position);
      mPosition.setText("...");
     }

    return view;
   }

   @Override
   public Filter getFilter() {
    return new Filter() {

     @SuppressWarnings("unchecked")
     @Override
     protected void publishResults(CharSequence constraint, FilterResults results) {
      mMain = (List<Model>) results.values;
      Adapter.this.notifyDataSetChanged();
     }

     @Override
     protected FilterResults performFiltering(CharSequence constraint) {
      List<Contest> filteredResults = getFilteredResults(constraint);
      FilterResults results = new FilterResults();
      results.values = filteredResults;
      return results;
     }

    };
   }

  }

}

我在 getFilteredResults

收到此错误
Cannot resolve method 'getFilteredResults(java.lang.CharSequence)'

我也在 mSearch.setOnQueryTextListener((SearchView.OnQueryTextListener) mContext);

处收到此错误
FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{...MainActivity}: java.lang.ClassCastException: ...InDraftActivity cannot be cast to android.widget.SearchView$OnQueryTextListener

java.lang.ClassCastException: ...MainActivity cannot be cast to android.widget.SearchView$OnQueryTextListener

解决方案

我通过在活动中实现 OnQueryTextListener 而不是片段来修复 SearchView 错误。

执行过滤需要看起来像

List<Contest> filteredResults = new ArrayList<Contest>();
FilterResults results = new FilterResults();
results.values = filteredResults;
results.count = filteredResults.size();

查看标记的答案。

【问题讨论】:

  • 什么是getFilteredResults,你定义了吗?因为我之前实现过这种代码,从来没有用过那种方法
  • 我删除了 getFilteredResults,现在 mMain.size() 在 publishResults 期间返回为 null。
  • 好吧,如果您删除了该方法,那么现在分配给filteredResults 的是什么?不是空的吗?
  • 您的活动是否实现了 OnQueryTextListener?
  • @Submersed,活动没有。 MainFragment 实现 SearchView.OnQueryTextListener

标签: java android listview searchview


【解决方案1】:

在您返回您的FilterResults 之前,您必须指定它的值和计数。目前你只是像这样指定值......

results.values = filteredResults;

在该行下,在您的 performFiltering(...) 方法中返回 results 之前,添加这一行...

results.count = filteredResults.size();

编辑:一个完全工作的适配器,带有我完成的项目中的过滤器

class ContactsAdapter extends BaseAdapter implements Filterable {

    private List<Contact> mData;
    private List<Contact> database;
    private LayoutInflater mInflater;
    private Context context;
    static boolean inMarkMode = false;

    ContactsAdapter(List<Contact> mData, List<Contact> database, Context context) {
        this.mData = mData;
        this.context = context;
        this.database = database;
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return mData.size();
    }

    /**
     * Modifies the way a contact is shown in its adapter depending on
     * displayChoice shared preference
     * 
     * @param position
     *            of the contact in its listview
     * @return <code>String</code> to display
     */
    @Override
    public String getItem(int position) {
        switch (context.getSharedPreferences("settings",
                HomeScreenActivity.MODE_PRIVATE).getInt("displayChoice", -1)) {
        case 1:
            return mData.get(position).getLastName() + " "
                    + mData.get(position).getFirstName();
        case 2:
            return mData.get(position).getFirstName() + " "
                    + mData.get(position).getMobileNumber();
        case 3:
            return mData.get(position).getLastName() + " "
                    + mData.get(position).getMobileNumber();
        default:
            return mData.get(position).getFirstName() + " "
                    + mData.get(position).getLastName();
        }
    }

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

    /**
     * Modifies the view shown in HomeScreenActivity depending on whether the
     * user has entered mark mode or not
     * 
     * @return <code>View</code> to display
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        CheckedTextView result = null;
        TextView normalResult = null;
        final String contactRow = getItem(position);

        if (inMarkMode) {// if user is in markMode, use the mark layout
            if (convertView == null) {
                result = (CheckedTextView) mInflater.inflate(
                        R.layout.home_screen_contacts_mark_view, parent, false);
            } else {
                result = (CheckedTextView) convertView;
            }
            result.setText(contactRow);
            result.setBackgroundResource(R.drawable.list_selector);
        } else { // if user NOT in markmode, use normal contacts view layout
            if (convertView == null) {
                normalResult = (TextView) mInflater.inflate(
                        R.layout.home_screen_contacts_view, parent, false);
            } else {
                normalResult = (TextView) convertView;
            }
            normalResult.setText(contactRow);
            normalResult.setBackgroundResource(R.drawable.list_selector);
        }

        if (inMarkMode) {
            return result;
        } else {
            return normalResult;
        }
    }

    int getItemIdAtPosition(int position) {
        return mData.get(position).getID();
    }

    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                FilterResults results = new FilterResults();
                // If there's nothing to filter on, return the original data for
                // your list
                if (charSequence == null || charSequence.length() == 0) {
                    results.values = database;
                    results.count = database.size();
                } else {
                    List<Contact> filterResultsData = new ArrayList<Contact>();

                    // if search details is 0, search fullName, else, search
                    // all details
                    if (HomeScreenActivity.searchAllDetails == 0) {
                        for (Contact c : database) {
                            if (c.getFullName().toLowerCase(Locale.ENGLISH)
                                    .contains(charSequence)) {
                                filterResultsData.add(c);
                            }
                        }
                    } else {
                        for (Contact c : database) {
                            if (c.getAllDetailsForSearch()
                                    .toLowerCase(Locale.ENGLISH)
                                    .contains(charSequence)) {
                                filterResultsData.add(c);
                            }
                        }
                    }

                    results.values = filterResultsData;
                    results.count = filterResultsData.size();
                }

                return results;
            }

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence charSequence,
                    FilterResults filterResults) {
                // set the data to the filter results and notifyDataSetChanged()
                mData = (List<Contact>) filterResults.values;
                notifyDataSetChanged();
            }
        };
    }
}

【讨论】:

  • 太棒了。谢谢你。 getFilteredResults 仍未解决。我认为 List filtersResults = getFilteredResults(constraint);已经足够好了。我应该怎么做才能修复这个错误?
  • @localhost 我不知道 getFilteredResults 是什么。您应该删除它并使List&lt;Contest&gt; filteredResults 等于某个arrayList,然后按照您想要的方式过滤arraylist,然后分配results.value 和results.count 然后返回它。我制作了一个使用这样的过滤器的联系人管理器应用程序,我会将其放在我的答案中,以便您查看。希望它会有一些用处。
  • 我明白了。这很有帮助。
猜你喜欢
  • 1970-01-01
  • 2014-07-28
  • 1970-01-01
  • 1970-01-01
  • 2021-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-26
相关资源
最近更新 更多