Android保存搜索历史

在我项目中,有这样一个功能实现:先看图

这里写图片描述

搜索后实时将搜索内容显示到RecyclerView中,可以删除单个历史,也可以清空全部,点击其中一项显示到EditText中。

将会涉及到的内容有:
RecyclerView使用方法
adapter接口
SharedPerference
我们先看一下布局:

R.layout.activity_favo_add

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/activity_background"
    android:orientation="vertical"
    tools:context="com.mymap.practice.ui.aty.favorite.FavoAddActivity">

    <android.support.v7.widget.Toolbar
        android:id="@+id/activity_favo_add_tb_toolbar"
        style="@style/toolbar_style"
        android:focusable="true"
        android:focusableInTouchMode="true">

        <EditText
            android:id="@+id/activity_favo_add_et_search"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginRight="50dp"
            android:background="@drawable/edit_backgroud"
            android:drawableLeft="@mipmap/search_icon"
            android:drawablePadding="@dimen/padding10"
            android:hint="@string/favo_search_hint"
            android:imeOptions="actionSearch"
            android:maxLength="30"
            android:maxLines="1"
            android:padding="@dimen/padding10"
            android:singleLine="true"
            android:textColor="@color/ios_btntext_blue"
            android:textColorHint="@color/gray"/>
    </android.support.v7.widget.Toolbar>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/activity_favo_add_tv_delAll"
        android:layout_below="@id/activity_favo_add_tb_toolbar"
        android:divider="@mipmap/input_line"
        android:orientation="vertical"
        android:showDividers="middle">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="14dp"
            android:layout_marginLeft="14dp"
            android:layout_marginTop="14dp"
            android:drawableLeft="@mipmap/search_icon"
            android:drawablePadding="10dp"
            android:text="@string/see_history"
            android:textColor="@color/ios_btntext_blue"
            android:textSize="@dimen/textSize18"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/activity_favo_add_rv_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </LinearLayout>

    <TextView
        android:id="@id/activity_favo_add_tv_delAll"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:drawableStart="@mipmap/ic_del_all"
        android:gravity="center"
        android:padding="10dp"
        android:text="@string/del_all"/>

</RelativeLayout>

《!-- item布局 --》R.layout.item_favo_add
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
                android:gravity="center_vertical"
              android:orientation="horizontal">

    <TextView
        android:id="@+id/item_favo_add_tv_history"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:paddingLeft="30dp"
        android:textSize="@dimen/textSize18"/>

    <ImageView
        android:padding="10dp"
        android:id="@+id/item_favo_add_iv_del"
        android:src="@mipmap/ic_del_all"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>
布局很简单,接下来我们先看一下Adapter吧
    public interface FavoAddClick
    {
        void onItemClick(View view, int position);

        void onDelClick(View view, int position);
    }

    public void setOnItemClickListener(FavoAddClick mOnItemClickListener)
    {
        this.listener = mOnItemClickListener;
    }

    // 删除一条
    public void removeData(int position)
    {
        list.remove(position); // 删掉对应的数据源
        notifyItemRemoved(position);
        notifyItemRangeChanged(position, getItemCount()); //刷 新
    }

    // 清空
    public void remoceAll()
    {
        list.clear();
    }

    // 添加一条数据
    public void add(String item, int position)
    {
        list.add(position, item);
        notifyItemInserted(position);
    }
在接口中,定义了点击事件和删除事件。注释都写得很清楚。其他的Adapter代码:
    public FavoAddAdapter(Context context, List<String> list)
    {
        mInflater = LayoutInflater.from(context);
        this.context = context;
        this.list = list;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        MyViewHolder holder = new MyViewHolder(mInflater.inflate(
                R.layout.item_favo_add, parent, false));
        return holder;
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position)
    {
        holder.tv_title.setText(list.get(position).toString());//为控件绑定数据

        if (null != listener)
        {
            final int pos = holder.getLayoutPosition();

            holder.itemView.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    listener.onItemClick(holder.itemView, pos);
                }
            });
            holder.iv_del.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    listener.onDelClick(v, position);
                    removeData(pos);
                }
            });
        }

    }

    @Override
    public int getItemCount()
    {
        return list == null ? 0 : list.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder
    {
        TextView tv_title;
        ImageView iv_del;

        public MyViewHolder(final View itemView)
        {
            super(itemView);
            tv_title = (TextView) itemView.findViewById(R.id.item_favo_add_tv_history);
            iv_del = (ImageView) itemView.findViewById(R.id.item_favo_add_iv_del);
        }
    }

OK,在类中,我们要在onCreate中初始化控件:
    private Activity activity = FavoAddActivity.this;
private SimpleDateFormat mFormat;
private FavoAddAdapter mAdapter;
private List<String> list; // 存放搜索内容的list
    /**
     * 初始化控件
     */
    private void initWidget()
    {
        //toolbar的控件
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayShowTitleEnabled(false); // Toolbar掉标题栏
        getSupportActionBar().setDisplayHomeAsUpEnabled(true); // 显示返回按钮

        rv_list.setHasFixedSize(true); // 确定了RecyclerView的高度此属性会提升性能
        rv_list.setLayoutManager(new LinearLayoutManager(this));
        rv_list.setItemAnimator(new DefaultItemAnimator());// 设置item动画
        rv_list.addItemDecoration(new DividerGridItemDecoration(this)); //分割线
        showSearchHistory(); // 显示搜索历史
    }
重点就是搜索历,我们先看一下搜索历史是如何显示的:
    /**
     * 从SP查询搜索历史,并按时间显示
     */
    private void showSearchHistory()
    {
        Map<String, String> hisAll = (Map<String, String>) SearchHistoryUtils.getAll(activity);
        //将key排序升序
        Object[] keys = hisAll.keySet().toArray();
        Arrays.sort(keys);
        int keyLeng = keys.length;
        //这里计算 如果历史记录条数是大于 可以显示的最大条数,则用最大条数做循环条件,防止历史记录条数-最大条数为负值,数组越界
        int hisLeng = keyLeng > HISTORY_MAX ? HISTORY_MAX : keyLeng;
        list = new ArrayList<>();
        for (int i = 1; i <= hisLeng; i++)
        {
            list.add(hisAll.get(keys[keyLeng - i]));
        }

        mAdapter = new FavoAddAdapter(activity, list);
        rv_list.setAdapter(mAdapter);
    }
其中,SearchHistoryUtils工具实现了按时间排序显示搜索历史,支持最大搜索历史条数,接下来将取到的数据填充到Adapter中。
接下来,看看监听事件:
// 搜索
        et_search.setOnEditorActionListener(new TextView.OnEditorActionListener()
        {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
            {
                if (actionId == EditorInfo.IME_ACTION_SEARCH)
                {
                    // 先隐藏键盘
                    KeyboardUtils.closeKeyboard(activity, et_search); // 显示键盘
                    // TODO Connect Service TO Search
			此处做联网搜索操作
                    // 将搜索记录保存到SP中
                    saveSearchHistory(et_search.getText().toString().trim());
                    mAdapter.add( et_search.getText().toString() , 0 ); //插入数据源
                    return true;
                }
                return false;
            }
        });
// 适配器点击事件
        mAdapter.setOnItemClickListener(new FavoAddAdapter.FavoAddClick()
        {
            @Override
            public void onItemClick(View view, int position) // 单击事件
            {
                et_search.setText(list.get(position).toString());
                et_search.requestFocus(); // 手动获得EditText焦点
                KeyboardUtils.openKeyboard(activity, et_search); // 显示键盘
                et_search.setSelection(list.get(position).toString().length()); // 将EditText光标移动到最后

            }

            @Override
            public void onDelClick(View view, int position) // 删除
            {
                // 获取map中value对应的key,然后删除key对应的某条数据
                String key = SearchHistoryUtils.valueGetKey(SearchHistoryUtils.getAll(activity), list.get(position).toString());
                SearchHistoryUtils.remove(activity, key);
            }
        });
        // 清空
        tv_delAll.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                clearsearchHistory();
                mAdapter.remoceAll();
            }
        });
KeyboardUtils是写好的工具类,实现了弹出、隐藏键盘。文章末尾我将会提供下载地址。

最后看一下对于map删除的操作过程:
    /**
     * 将历史记录保存至sp中,key=当前时间(20160302133455,便于排序) ,value=关键字
     *
     * @param keyWords 搜索内容
     */
    private void saveSearchHistory(String keyWords)
    {
        //保存之前要先查询sp中是否有该value的记录,有则删除.这样保证搜索历史记录不会有重复条目
        Map<String, String> historys = (Map<String, String>) SearchHistoryUtils.getAll(activity);
        for (Map.Entry<String, String> entry : historys.entrySet())
        {
            if (keyWords.equals(entry.getValue()))
            {
                SearchHistoryUtils.remove(activity, entry.getKey());
            }
        }
        mFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        // 以时间为key,保存搜索记录
        SearchHistoryUtils.put(activity, "" + mFormat.format(new Date()), keyWords);
        // 刷新适配器
        mAdapter.notifyDataSetChanged();
    }


    /**
     * 清除历史记录
     */
    private void clearsearchHistory()
    {
        SearchHistoryUtils.clear(this);
        //同时刷新历史记录显示页面
        mAdapter.notifyDataSetChanged();
    }
/**
* 最后是标题栏返回按钮监听事件
**/
    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        switch (item.getItemId())
        {
            case android.R.id.home:
                ActivityCollector.removeActivity(this);
                break;
        }
        return super.onOptionsItemSelected(item);
    }
哦,对了,Toolbar只有在AppCompatActivity中才可以使用哦。
本文使用的SearchHistoryUtils是基于某同志分享的工具类基础上加了根据value得到key的方法,被很多人转载却并没有标注作者是谁,在此对作者表示感谢。
由于时间有限并没有写成Demo而是把用到的类和布局抽了出来,在此奉上

http://download.csdn.net/detail/u012552275/9695668


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值