使用RecyclerView过滤的SearchView过滤器,结果错误

时间:2016-12-29 11:54:30

标签: android android-recyclerview searchview android-filterable

我有一个带有RecyclerView的SearchView,它可以搜索联系人列表。但搜索结果结果似乎是错误的。有些过滤正在发生,但不是正确的过滤。例如,如果我搜索字符“a”,它将过滤掉一些随机的内容而不是以a开头的联系人。代码片段如下。

活动类

    public class MembersActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {

@BindView(R.id.meetup_members_recycler_view)
RecyclerView mRecyclerView;

CustomContactAdapter contactAdapter;
List<Contact> contactList = new ArrayList();
private SearchView mSearchView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_meetup_members);
    ButterKnife.bind(this);
    mSearchView = (SearchView) findViewById(R.id.action_search);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

    getAllContacts();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);

    final MenuItem searchItem = menu.findItem(R.id.action_search);
    final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
    searchView.setOnQueryTextListener(this);

    return true;
}

private void getAllContacts() {

    Contact contact;

    ContentResolver contentResolver = getContentResolver();
    Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
    if (cursor.getCount() > 0) {
        while (cursor.moveToNext()) {

            int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
            if (hasPhoneNumber > 0) {
                String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
                String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

                contact = new Contact();
                contact.setName(name);

                Cursor phoneCursor = contentResolver.query(
                        ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                        null,
                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
                        new String[]{id},
                        null);
                if (phoneCursor.moveToNext()) {
                    String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                    contact.setMobile(phoneNumber);
                }

                phoneCursor.close();
                contactList.add(contact);
            }
        }

        contactAdapter = new CustomContactAdapter(getApplicationContext(),contactList);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.setAdapter(contactAdapter);
    }
}


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

@Override
public boolean onQueryTextChange(String newText) {
    contactAdapter.getFilter().filter(newText);
    return true;
}
}

适配器类

   public class CustomContactAdapter extends RecyclerView.Adapter<CustomContactAdapter.ContactViewHolder>
    implements CompoundButton.OnCheckedChangeListener,Filterable {

Context mContext;
LayoutInflater mInflater;
private List<Contact> contactList = new ArrayList<Contact>();
private List<Contact> filterContactList = new ArrayList<Contact>();
private ContactFilter contactFilter;

public CustomContactAdapter(Context context,List<Contact> contacts)
{
    mInflater = LayoutInflater.from(context);
    mContext = context;
    this.contactList = contacts;
    this.filterContactList = contacts;

}

public static class ContactViewHolder extends RecyclerView.ViewHolder
        implements View.OnClickListener {
    @BindView(R.id.member_name)
    TextView mContactName;
    @BindView(R.id.member_mobile)
    TextView mPhoneNumber;
    @BindView(R.id.member_image)
    ImageView mImage;

    public ContactViewHolder(View view) {
        super(view);
        ButterKnife.bind(this, view);
        view.setOnClickListener(this);
    }

    @Override
    public void onClick(View view){

    }
}

@Override
public CustomContactAdapter.ContactViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.member_list_row, parent, false);

    return new CustomContactAdapter.ContactViewHolder(itemView);
}

@Override
public void onBindViewHolder(CustomContactAdapter.ContactViewHolder holder, int position) {

    Contact contact = contactList.get(position);
    holder.mContactName.setText(contact.getName());
    holder.mPhoneNumber.setText(contact.getMobile());

}

@Override
public int getItemCount() {
    return filterContactList.size();
}

@Override
public Filter getFilter() {
    if(contactFilter == null)
        contactFilter = new ContactFilter();
    return contactFilter;
}


private class ContactFilter extends Filter {

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults filterResults = new FilterResults();
        if (constraint!=null && constraint.length()>0) {
            ArrayList<Contact> tempList = new ArrayList<Contact>();

            for (Contact contact : contactList) {
                if (contact.getName().toLowerCase().contains(constraint.toString().toLowerCase())) {
                    tempList.add(contact);
                }
            }

            filterResults.count = tempList.size();
            filterResults.values = tempList;
            System.out.println("performFiltering:SearchFoundCount "+ tempList.size());
            System.out.println("performFiltering:ActualSize "+ contactList.size());

        } else {
            filterResults.count = contactList.size();
            filterResults.values = contactList;
        }

        return filterResults;
    }

    /**
     * Notify about filtered list to ui
     * @param constraint text
     * @param results filtered result
     */
    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        filterContactList = (ArrayList<Contact>) results.values;
        notifyDataSetChanged();
    }
}
}

无法做到这一点,可能是我想念的傻事。 感谢任何帮助。

3 个答案:

答案 0 :(得分:2)

我在我的应用程序中做了类似的事情。 在onBindViewHolder中,您应该使用筛选列表而不是初始列表

@Override
public void onBindViewHolder(CustomContactAdapter.ContactViewHolder holder, int position) {

Contact contact = filterContactList.get(position);
...

希望这适合你。 :)

答案 1 :(得分:1)

您可能希望搜索结果以您的角色开头,然后更改您的FilterResults方法。

for (Contact contact : contactList) {
            if (contact.getName().toLowerCase().startsWith(constraint.toString().toLowerCase())) {
                tempList.add(contact);
            }
        }

答案 2 :(得分:0)

这也可行。只需更改以下代码

即可
@SuppressWarnings("unchecked")
     @Override
     protected void publishResults(CharSequence constraint, FilterResults 
      results) {
     contactList= (ArrayList<Contact>) results.values;
     notifyDataSetChanged();
}