在我项目中,有这样一个功能实现:先看图
搜索后实时将搜索内容显示到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