我的自定义搜索视图无法正常工作,当搜索输入为空时不显示原始列表

Posted

技术标签:

【中文标题】我的自定义搜索视图无法正常工作,当搜索输入为空时不显示原始列表【英文标题】:My custom search view is not working correctly, not showing original list when search input is null 【发布时间】:2021-06-02 19:32:47 【问题描述】:

我正在尝试在我的活动中实现自定义可搜索微调器,但代码中有问题,我找不到它。查看下面的屏幕截图以了解我的问题。

snap1 这是包含三个项目的原始列表视图,尚未添加搜索过滤器

snap2 这是搜索过滤器后的列表视图

snap3 这是删除搜索后的列表视图。

正如您在第三个屏幕截图中看到的那样,在清除搜索过滤器后,列表视图没有显示所有三个项目。你能看出我在代码中犯了什么错误吗?

ListAdapter.java

public class ListAdapter extends ArrayAdapter<SpinnerItem> 

    private List<SpinnerItem> items;
    private Context context;
    private Filter filter;
    public ListAdapter(@NonNull Context context, int resource, List<SpinnerItem> items) 
        super(context, resource);
        this.context = context;
        this.items = items;
        this.filter = new CustomItemsFilter();
    

    @Nullable
    @Override
    public SpinnerItem getItem(int position) 
        return items.get(position);
    

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

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) 

        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rootView = inflater.inflate(R.layout.list_item,parent,false);
        TextView textView = rootView.findViewById(R.id.itemTitle);
        TextView textView1 = rootView.findViewById(R.id.itemSubTitle);
        TextView textView2 = rootView.findViewById(R.id.itemSign);

        textView.setText(items.get(position).getTitle());
        textView1.setText(items.get(position).getSubTitle());
        textView2.setText(items.get(position).getSign());
        return rootView;
    

    @NonNull
    @Override
    public Filter getFilter() 

        if(filter == null) 
            filter = new CustomItemsFilter();
        
        return filter;
    

    private class CustomItemsFilter extends Filter 

        @Override
        protected FilterResults performFiltering(CharSequence constraint) 

            FilterResults filterResults = new FilterResults();

            if(constraint != null && constraint.toString().length() > 0) 
                constraint = constraint.toString().toLowerCase();
                List<SpinnerItem> allItems = new ArrayList<SpinnerItem>();
                List<SpinnerItem> filterItems = new ArrayList<SpinnerItem>();
                synchronized (this) 
                    allItems.addAll(items);
                
                for (int i = 0; i < allItems.size(); ++i) 
                    SpinnerItem item = allItems.get(i);
                    if(item.getTitle().contains(constraint) || item.getSubTitle().contains(constraint) || item.getSign().contains(constraint)) 
                        filterItems.add(item);
                    
                
                filterResults.count = filterItems.size();
                filterResults.values = filterItems;
            
            else 
                synchronized (this) 
                    filterResults.values = items;
                    filterResults.count = items.size();
                
            
            return filterResults;
        

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) 

            if(results.count > 0) 
                items = (List<SpinnerItem>) results.values;
                notifyDataSetChanged();
            
        

    

SpinnerDialog.java

public class SpinnerDiaglog implements SearchView.OnCloseListener, SearchView.OnQueryTextListener

     private List<SpinnerItem> items;
     private OnSpinnerItemClick onSpinnerItemClick;
     private Activity context;
     private SearchView searchView;
     private DialogInterface.OnClickListener onClickListener;
     private ListAdapter adapter;
     private OnSearchTextChanged onSearchTextChanged;
     private ListView listView;
     private AlertDialog dialog;

    public SpinnerDiaglog() 
    

    public SpinnerDiaglog(Activity context, List<SpinnerItem> items) 
         this.context = context;
         this.items = items;
     

    public void onCreateDialog() 
        View rootView = context.getLayoutInflater().inflate(R.layout.spinner_dialog,null);
        //setData(rootView);
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
        alertDialog.setView(rootView);
        alertDialog.setPositiveButton("CLOSE",onClickListener);
        alertDialog.setTitle("Select Item");

        SearchManager searchManager = (SearchManager) context.getSystemService(Context
                .SEARCH_SERVICE);

        searchView = rootView.findViewById(R.id.search);
        searchView.setSearchableInfo(searchManager.getSearchableInfo(context.getComponentName()));
        searchView.setOnQueryTextListener(this);
        searchView.setOnCloseListener(this);
        searchView.setIconifiedByDefault(false);
        searchView.clearFocus();

        listView = rootView.findViewById(R.id.listItems);
        adapter = new ListAdapter(context,R.layout.list_item,items);
        listView.setAdapter(adapter);

        dialog = alertDialog.create();
        dialog.show();

        listView.setOnItemClickListener((parent, view, position, id) -> 
            onSpinnerItemClick.onClick(adapter.getItem(position),position);
            dialog.dismiss();
        );
    

    public void setOnSpinnerItemClickListener(OnSpinnerItemClick onSpinnerItemClick) 
        this.onSpinnerItemClick = onSpinnerItemClick;
    
    public void setOnSearchTextChangedListener(OnSearchTextChanged onSearchTextChanged) 
        this.onSearchTextChanged = onSearchTextChanged;
    


    @Override
    public boolean onQueryTextSubmit(String query) 
         searchView.clearFocus();
        return false;
    

    @Override
    public boolean onQueryTextChange(String newText) 

         if(TextUtils.isEmpty(newText)) 
             ((ListAdapter) listView.getAdapter()).getFilter().filter(null);
         
         else 
             ((ListAdapter) listView.getAdapter()).getFilter().filter(newText);
         
        if (null != onSearchTextChanged) 
            onSearchTextChanged.onSearchTextChanged(newText);
        
        return true;
    

    public interface OnSpinnerItemClick 

        void onClick(SpinnerItem item, int position);
    

    public interface OnSearchTextChanged 
        void onSearchTextChanged(String strText);
    


    @Override
    public boolean onClose() 
        return false;
    



MainActivity.java

public class MainActivity2 extends AppCompatActivity 

    private SpinnerDiaglog spinnerDiaglog;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        Button button = findViewById(R.id.show);

        List<SpinnerItem> items = new ArrayList<>();
        items.add(new SpinnerItemImp("Title","subTitle","sign"));
        items.add(new SpinnerItemImp("aitle","subTitle","sign"));
        items.add(new SpinnerItemImp("Tiastle","subTitle","sign"));
        button.setOnClickListener(v -> 

            spinnerDiaglog = new SpinnerDiaglog(MainActivity2.this,items);
            spinnerDiaglog.onCreateDialog();

        );
    

SpinnerItemImp.java

public class SpinnerItemImp implements SpinnerItem 

    private String title;
    private String subTitle;
    private String sign;

    public SpinnerItemImp(String title, String subTitle, String sign) 
        this.title = title;
        this.subTitle = subTitle;
        this.sign = sign;
    

    @Override
    public String getTitle() 
        return title;
    

    @Override
    public String getSubTitle() 
        return subTitle;
    

    @Override
    public String getSign() 
        return sign;
    

【问题讨论】:

【参考方案1】:

您保留一个列表items,当您第一次应用过滤器时,该列表会被修改。因此,在下一个过滤器中,您实际上是从过滤后的列表中过滤,而不是实际的列表。

您需要单独维护一个完整列表并在其上应用过滤器而不是在过滤后的列表上。下面是一个例子:

public class ListAdapter extends ArrayAdapter<SpinnerItem> 
    private List<SpinnerItem> items;
    private List<SpinnerItem> allItems;
    private Context context;
    private Filter filter;
    public ListAdapter(@NonNull Context context, int resource, List<SpinnerItem> items) 
        super(context, resource);
        this.context = context;
        this.items = items;
        this.filter = new CustomItemsFilter();
        allItems=new ArrayList<>(items);
    

    @Override
    public SpinnerItem getItem(int position) 
        return items.get(position);
    

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

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) 
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rootView = inflater.inflate(R.layout.list_item,parent,false);
        return rootView;
    

    @NonNull
    @Override
    public Filter getFilter() 
        if(filter == null) 
            filter = new CustomItemsFilter();
        
        return filter;
    

    private class CustomItemsFilter extends Filter 
        @Override
        protected FilterResults performFiltering(CharSequence constraint) 
            items.clear();
            FilterResults filterResults = new FilterResults();
            constraint = constraint.toString().trim().toLowerCase();
            if (constraint.length() > 0) 
                for (int i = 0; i < allItems.size(); ++i) 
                    SpinnerItem item = allItems.get(i);
                    if (item.getTitle().contains(constraint) || item.getSubTitle().contains(constraint) || item.getSign().contains(constraint)) 
                        items.add(item);
                    
                
             else 
                items.addAll(allItems);
            
            filterResults.values = items;
            filterResults.count = items.size();
            return filterResults;
        

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) 
           
                items = (List<SpinnerItem>) results.values;
                notifyDataSetChanged();
           
        
    

【讨论】:

以上是关于我的自定义搜索视图无法正常工作,当搜索输入为空时不显示原始列表的主要内容,如果未能解决你的问题,请参考以下文章

如何检测标签在Javascript中为空?

当搜索字符串为空时,带有连接的搜索查询显示所有行

当我的搜索字段为空时,如何在不搜索结果的情况下呈现页面,但在搜索时仍然异步呈现?

反应搜索 onChange 取消请求

仅当搜索框不为空时才显示项目匹配内容

字段为空时不触发远程属性