……

个人技术总结—列表搜索

1、技术概述

  1. 技术概述

利用数据适配器类实现列表搜索功能。

  1. 原因

需要为用户提供搜索筛选功能,方便用户快速查找信息。

  1. 难点

数据适配器及过滤器类的书写,数据刷新显示。

2、技术详述

最初在网上查阅了大量的代码,通过阅读多分代码比较会发现他们的一些相同的地方,这部分就是这个功能的关键部分了,然后仔细阅读这部分的代码,大致搞懂它的实现逻辑之后就自己动手参照着写代码了。实现过程如下:

  1. 写一个类实现适配器接口,用于适配需要展示的列表数据

/**
 *数据适配器
 *
 */
class RecomendAdapter extends BaseAdapter implements Filterable {
    Context context;
    List<Periodic> data; //这个数据是会改变的,所以要有个变量来备份一下原始数据
    List<Periodic> backData;//用来备份原始数据
    MyFilter mFilter ;

    
    public RecomendAdapter(Context context, List<Periodic> data) {
        this.context = context;
        this.data = data;
        backData = data;
    }

    
    @Override
    public int getCount() {
        return data.size();
    }

    
    @Override
    public Object getItem(int i) {
        return data.get(i);
    }

    
    @Override
    public long getItemId(int i) {
        return 0;
    }

    
    public  void addItem(Periodic obj){
        data.add(obj);
    }

    
    public void removeItem(int index){
        Periodic tep = data.get(index);
        backData.remove(tep);
        data.remove(tep);
    }


    public void clearAll(){
       data.clear();
       backData.clear();
    }

    
    public void setData(List<Periodic> data){
        this.data = data;
        backData = data;
    }
    
    
    @Override
    public View getView(int position, View view, ViewGroup viewGroup) {
        if (view ==null){
            view = LayoutInflater.from(context).inflate(R.layout.periodic_list_item,null);
        }

       //从数组中得到数据并然后给页面组件设置值
        Periodic periodicItem=data.get(position);
        TextView nameView = (TextView)view.findViewById(R.id.periodic_item_name);
        TextView moneyView = (TextView)view.findViewById(R.id.periodic_item_money);
        TextView startView = (TextView)view.findViewById(R.id.periodic_item_start);
        TextView endView = (TextView)view.findViewById(R.id.periodic_item_end);
        //设置periodic项目的值,信息
        //时间格式化
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String tmpMoney=null;
        if(periodicItem.getType()==0){//支出
            tmpMoney = "-" + String.valueOf(periodicItem.getPeriodic_money());
            moneyView.setTextColor(Color.parseColor("#ff0000"));
        }
        else {//收入
            tmpMoney = "+" + String.valueOf(periodicItem.getPeriodic_money());
            moneyView.setTextColor(Color.parseColor("#00ff00"));
        }
        nameView.setText(periodicItem.getPeriodic_name());
        moneyView.setText(String.valueOf(periodicItem.getPeriodic_money()));
        startView.setText(format.format(periodicItem.getStart()));
        endView.setText(format.format(periodicItem.getEnd()));
        return view;
    }
    
    
    /**
     * 当ListView调用setTextFilter()方法的时候,便会调用该方法
     * @return 过滤器类
     */
    @Override
    public Filter getFilter() {
        if (mFilter ==null){
            mFilter = new MyFilter();
        }
        return mFilter;
    }
    
}
  1. 写一个过滤类根据用户输入进行数据筛选,并刷新数据
 /**
     * 定义一个过滤器的类来定义过滤规则
     */
    class MyFilter extends Filter{
        /**
         * 义过滤规则
         * @param charSequence 输入的字符文本
         * @return
         */
        @Override
        protected FilterResults performFiltering(CharSequence charSequence) {
            FilterResults result = new FilterResults();
            List<Periodic> list ;
            if (TextUtils.isEmpty(charSequence)){//当过滤的关键字为空的时候,我们则显示所有的数据
                list  = backData;
            }else {//否则把符合条件的数据对象添加到集合中
                list = new ArrayList<>();
                for (Periodic recomend:backData){
                    if (recomend.getPeriodic_name().contains(charSequence)){
                        list.add(recomend);
                    }
                }
            }
            result.values = list; //将得到的集合保存到FilterResults的value变量中
            result.count = list.size();//将集合的大小保存到FilterResults的count变量中
            return result;
        }


        /**
         * 告诉适配器更新界面
         * @param charSequence
         * @param filterResults
         */
        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
            data = (List<Periodic>)filterResults.values;
            if (filterResults.count>0){
                notifyDataSetChanged();//通知数据发生了改变
            }else {
                notifyDataSetInvalidated();//通知数据失效
            }
        }
    }

  1. 为列表注册适配器并添加搜索框事件响应处理
 searchPeriodic.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            /**
             * 当点击搜索按钮时触发该方法
             * @param query 输入的字符串
             * @return
             */
            @Override
            public boolean onQueryTextSubmit(String query) {
                //提交搜索后的处理逻辑
                return false;
            }
            
            
            /**
             * 当搜索内容改变时触发该方法,时刻监听输入搜索框的值
             * @param newText 当前输入的文本
             * @return
             */
            @Override
            public boolean onQueryTextChange(String newText) {
                //如果newText长度不为0
                if (TextUtils.isEmpty(newText)){
                    //清除ListView的过滤
                    listView.clearTextFilter();
                }else{
                    //使用用户输入的内容对ListView的列表项进行过滤
                    listView.setFilterText(newText);
                }
                return true;
            }
        });

3、遇到的问题和解决方法

  • 列表数据不刷新

每次更改数据后要调用数据适配器的notifyDataSetChanged() 方法通知数据的变化

4、总结

最初列表展示的适配器是简单的数组适配器,并不能满足搜索的功能需求,在查阅资料后发现需要重写适配器才能达到功能需求,刚开始感觉这挺难的,但好在网上的资料足够丰富,也找到了一些例子可供参考,最后还是实现了这个功能。总之,遇到困难要抱着积极的态度去尝试解决。

5、参考文献,博客等

posted @ 2020-06-23 23:26  有夜之夜  阅读(141)  评论(0编辑  收藏  举报