AutoCompleteTextView 的自定义过滤器在单击时返回错误的字符串

Posted

技术标签:

【中文标题】AutoCompleteTextView 的自定义过滤器在单击时返回错误的字符串【英文标题】:Custom Filter for AutoCompleteTextView returns wrong string on click 【发布时间】:2018-09-09 11:45:32 【问题描述】:

我为我的AutoCompleteTextView 编写了自定义ArrayAdapter 和自定义Filter。它正确显示了所有内容,但是当我过滤建议并单击一个项目时,它会获取显示所有项目时建议列表中此位置的项目的字符串。我做了截图来澄清我的意思:

这是我的代码:

public class AutoCompleteCountryAdapter extends ArrayAdapter<CountryItem> 
private List<CountryItem> countryList;
private List<CountryItem> filteredCountryList = new ArrayList<>();

public AutoCompleteCountryAdapter(@NonNull Context context, @NonNull List<CountryItem> countryList) 
    super(context, 0, countryList);
    this.countryList = countryList;


@Override
public int getCount() 
    return filteredCountryList.size();


@NonNull
@Override
public Filter getFilter() 
    return countryFilter;


@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) 
    CountryItem countryItem = filteredCountryList.get(position);
    LayoutInflater inflater = LayoutInflater.from(getContext());

    if (convertView == null) 
        convertView = inflater.inflate(
                R.layout.country_autocomplete_row, parent, false
        );
    

    TextView textViewName = convertView.findViewById(R.id.text_view_name);
    ImageView imageViewFlag = convertView.findViewById(R.id.image_view_flag);
    textViewName.setText(countryItem.getCountryName());
    imageViewFlag.setImageResource(countryItem.getFlagImage());

    return convertView;


private Filter countryFilter = new Filter() 

    private List<CountryItem> suggestions = new ArrayList<>();

    @Override
    protected FilterResults performFiltering(CharSequence constraint) 
        suggestions.clear();
        FilterResults results = new FilterResults();

        if (constraint == null || constraint.length() == 0) 
            suggestions.addAll(countryList);
         else 
            String filterPattern = constraint.toString().toLowerCase().trim();

            for (CountryItem item : countryList) 
                if (item.getCountryName().toLowerCase().contains(filterPattern)) 
                    suggestions.add(item);
                
            
        
        results.values = suggestions;
        results.count = suggestions.size();
        return results;
    

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) 
        filteredCountryList.clear();
        filteredCountryList.addAll((List) results.values);
        notifyDataSetChanged();
    

    @Override
    public CharSequence convertResultToString(Object resultValue) 
        return ((CountryItem) resultValue).getCountryName();
    
;

【问题讨论】:

你能把处理列表点击的活动代码贴出来 我不处理那里的点击,它在过滤器的 convertResultToString 方法中处理。但对我来说,它显示的结果与下拉列表中的结果不同 【参考方案1】:

我解决了。 我不知道为什么这没有出现在我找到的任何教程中(包括 Materialdoc 教程),但您还必须在适配器中覆盖 getItem,以便从过滤后的列表中选择它的项目,而不是从原始列表中选择:

 public CountryItem getItem(int position) 
    return filteredCountryList.get(position);

【讨论】:

【参考方案2】:

我为过滤用户联系人的用户联系人适配器提供了一个使用 recylerview 适配器的适配器类。您可以根据代码更改您的要求..

public class InviteContactAdapter extends RecyclerView.Adapter<InviteContactAdapter.ItemViewHolder> implements Filterable 
private List<UserContact> mContactList = new ArrayList<>();
private List<UserContact> mContectFilter = new ArrayList<>();
private Context mContext;
private CustomFilter mFilter;
public List<String> mEmailList = new ArrayList<>();

public InviteContactAdapter(Context context, List<UserContact> mContactList) 
    mContext = context;
    this.mContactList = mContactList;
    this.mContectFilter = mContactList;
    mFilter = new CustomFilter();


public onItemClickListener onItemClickListener;

public void setOnItemClickListener(InviteContactAdapter.onItemClickListener onItemClickListener) 
    this.onItemClickListener = onItemClickListener;


@Override
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) 
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.invite_contact_row_layout, viewGroup, false);
    return new ItemViewHolder(view);


public interface onItemClickListener 
    void onClick(UserContact contact);


@Override
public Filter getFilter() 
    return mFilter;


@Override
public void onBindViewHolder(final ItemViewHolder itemViewHolder, int i) 
    final UserContact contact = mContectFilter.get(i);
    itemViewHolder.mTvUserNane.setText(contact.getUserName().trim());
    itemViewHolder.mTvUserEmail.setText(contact.getUserEmail().trim());
    if (contact.isSelect())
        itemViewHolder.mIvSelect.setImageResource(R.drawable.check_contect);
    else
        itemViewHolder.mIvSelect.setImageResource(R.drawable.un_check_contact);


    itemViewHolder.itemView.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 

            if (contact.isSelect()) 
                contact.setSelect(false);
                itemViewHolder.mIvSelect.setImageResource(R.drawable.un_check_contact);
             else 
                contact.setSelect(true);
                itemViewHolder.mIvSelect.setImageResource(R.drawable.check_contect);
            
        
    );



@Override
public int getItemCount() 
    return mContectFilter.size();


public class ItemViewHolder extends RecyclerView.ViewHolder 
    private TextView mTvUserNane, mTvUserEmail;
    private ImageView mIvSelect;

    public ItemViewHolder(View itemView) 
        super(itemView);
        mTvUserEmail = itemView.findViewById(R.id.icrlTvUserEmail);
        mTvUserNane = itemView.findViewById(R.id.icrlTvUserName);
        mIvSelect = itemView.findViewById(R.id.icrlIvSelect);
    


public List<String> getEmail() 
    mEmailList.clear();
    for (UserContact contact : mContectFilter) 
        if (contact.isSelect()) 
            mEmailList.add(contact.getUserEmail());
        
    
    return mEmailList;


/**
 * this class for filter data.
 */
class CustomFilter extends Filter 

    @Override
    protected FilterResults performFiltering(CharSequence charSequence) 
        FilterResults results = new FilterResults();
        if (charSequence != null && charSequence.length() > 0) 
            ArrayList<UserContact> filters = new ArrayList<>();
            charSequence = charSequence.toString().toUpperCase();
            for (int i = 0; i < mContactList.size(); i++) 
                if (mContactList.get(i).getUserName().toUpperCase().contains(charSequence) || mContactList.get(i).getUserEmail().toUpperCase().contains(charSequence)) 
                    UserContact contact = new UserContact();
                    contact.setUserName(mContactList.get(i).getUserName());
                    contact.setUserEmail(mContactList.get(i).getUserEmail());
                    filters.add(contact);

                
            
            results.count = filters.size();
            results.values = filters;

         else 
            results.count = mContactList.size();
            results.values = mContactList;
        
        return results;
    

    @Override
    protected void publishResults(CharSequence charSequence, FilterResults filterResults) 
        mContectFilter = (ArrayList<UserContact>) filterResults.values;
        notifyDataSetChanged();
    

【讨论】:

【参考方案3】:
ArrayList<YourModel> arrayList = new ArrayList<>();
arrayList.addAll(yourList);

AutoCompleteAdapter autoCompleteAdapter = new AutoCompleteAdapter(context, arrayList);
autoCompleteTextView.setAdapter(brandAdapter);

autoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() 
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
        YourModel model = (YourModel) autoCompleteAdapter.getItem(position);
        autoCompleteTextView.setText(model.getText());
        autoCompleteTextView.setSelection(model.getText().length());
    
);

AutoCompleteAdapter.java

public class AutoCompleteAdapter extends BaseAdapter implements Filterable 

    private Context context;
    private ArrayList<YourModel> originalList;
    private ArrayList<YourModel> suggestions = new ArrayList<>();
    private Filter filter = new CustomFilter();

    public AutoCompleteAdapter(Context context, ArrayList<YourModel> originalList) 
        this.context = context;
        this.originalList = originalList;
    

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        try 
            if (convertView == null) 
                convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_filter, parent, false);
            

            YourModel model = suggestions.get(position);

            AppCompatTextView tvTitle = convertView.findViewById(R.id.tvTitle);
            tvTitle.setText(model.getText());
         catch (NullPointerException e) 
            e.printStackTrace();
         catch (Exception e) 
            e.printStackTrace();
        

        return convertView;
    

    @Override
    public Object getItem(int position) 
        return suggestions.get(position);
    

    @Override
    public long getItemId(int position) 
        return 0;
    

    @Override
    public int getCount() 
        return suggestions.size();
    

    @Override
    public Filter getFilter() 
        return filter;
    

    private class CustomFilter extends Filter 
        @Override
        protected FilterResults performFiltering(CharSequence constraint) 
            suggestions.clear();

            if (originalList != null && constraint != null) 
                for (int i = 0; i < originalList.size(); i++) 
                    if (originalList.get(i).getText().toLowerCase().contains(constraint.toString().toLowerCase().trim())) 
                        suggestions.add(originalList.get(i));
                    
                
            
            FilterResults results = new FilterResults();
            results.values = suggestions;
            results.count = suggestions.size();

            return results;
        

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) 
            if (results.count > 0) 
                notifyDataSetChanged();
             else 
                notifyDataSetInvalidated();
            
        
    

【讨论】:

以上是关于AutoCompleteTextView 的自定义过滤器在单击时返回错误的字符串的主要内容,如果未能解决你的问题,请参考以下文章

在AutocompleteTextview的下拉列表中自定义分隔符/分隔符

将其值设置为“”后无法过滤 AutoCompleteTextView

Android自己主动提示文本框(AutoCompleteTextView)

AutoCompleteTextView(自动完成文本框)的基本使用

Arraylist 中有 1000 个条目的 AutocompleteTextView 不起作用

AutoCompleteTextView的使用