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

My custom search view is not working correctly, not showing original list when search input is null

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

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

您保留了一个列表 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();
           
        }
    }
}