Tengo un SearchView con un RecyclerView que intenta buscar una lista de contactos. Pero los resultados de los resultados de búsqueda parecen estar equivocados. Está ocurriendo algo de filtrado pero no el correcto. Por ejemplo, si busco con el carácter "a", filtrará algo aleatorio en lugar de Contactos que comienzan con a. Fragmentos de código como a continuación.

Clase de actividad

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

Clase de adaptador

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

No puedo hacer esto bien, puede ser algo tonto que me estoy perdiendo. Agradezco cualquier ayuda.

1
user2695433 29 dic. 2016 a las 14:54

3 respuestas

La mejor respuesta

Estaba haciendo algo similar en mi aplicación. En onBindViewHolder debe usar la lista filtrada en lugar de la inicial

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

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

Espero que esto funcione para usted. :)

4
Hristo Stoyanov 29 dic. 2016 a las 12:09

Es posible que desee que su resultado de búsqueda comience con su personaje y luego cambie su método FilterResults.

for (Contact contact : contactList) {
            if (contact.getName().toLowerCase().startsWith(constraint.toString().toLowerCase())) {
                tempList.add(contact);
            }
        }
1
Jahidur Rahman 29 dic. 2016 a las 12:18

Esto también podría funcionar. Solo cambia el siguiente código

@SuppressWarnings("unchecked")
     @Override
     protected void publishResults(CharSequence constraint, FilterResults 
      results) {
     contactList= (ArrayList<Contact>) results.values;
     notifyDataSetChanged();
}
0
Thriveni 12 ene. 2018 a las 12:15