Android 一般项目的 搜索功能 历史记录排序实现
来源:互联网 发布:罗德曼生涯数据 编辑:程序博客网 时间:2024/06/05 08:14
先看张效果图,
素材有点low,软键盘右下角回车变成搜索按钮。这种实现只需要在edittext上加入Android:imeOptions="actionSearch"即可,这个也根据版本的2.3以上就必须添加android:singleLine="true",这个可以理解,因为单行为true时,回车就不会起作用。
先看下整体的布局
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><LinearLayout android:layout_width="match_parent" android:layout_height="45dp" android:background="#14141F" android:gravity="center_vertical" android:orientation="horizontal" android:paddingBottom="6dp" android:paddingTop="6dp"> <ImageView android:id="@+id/iv_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="14dp" android:paddingRight="14dp" android:src="@mipmap/icon"/> <RelativeLayout android:id="@+id/rl_search_layout" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal"> <EditText android:id="@+id/et_search" android:layout_width="match_parent" android:layout_height="30dp" android:layout_centerVertical="true" android:layout_marginLeft="10dp" android:background="@null" android:hint="输入商品名或者店铺名称" android:imeOptions="actionSearch" android:singleLine="true" android:textColor="#FFFFFF" android:textColorHint="#7F7F7F" android:textSize="14sp" /> </RelativeLayout> <TextView android:id="@+id/tv_cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="14dp" android:layout_marginRight="14dp" android:gravity="center_vertical" android:text="取消" android:textColor="#FFFFFF" android:textSize="18sp" /></LinearLayout><LinearLayout android:id="@+id/ll_search_history" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <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/brand_search_history_icon" android:drawablePadding="10dp" android:text="历史记录" android:textColor="#333333" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#dfdfdf" /> <ListView android:id="@+id/listView" android:divider="@null" android:layout_width="match_parent" android:layout_height="wrap_content"> </ListView> </LinearLayout></LinearLayout>
布局大体就为这样,整个流程就是当用户在输入框输入内容时,点击软键盘的搜索按钮,会做出一定的逻辑处理,Demo就Toast一句话而已。保存搜索内容作为搜索历史记录,在保存的时候采用的sp(SharedPreferences)来实现。
需要注意的是 setOnEditorActionListener这个方法,并不是在我们点击EditText的时候触发,也不是在我们对EditText进行编辑时触发,而是在我们编辑完之后点击软键盘上的回车键才会触发。我们把回车键改为搜索键,所以当我们点击搜索时,监听方法会触发,实现搜索的具体逻辑。
//监听软键盘输入法按下【搜索】事件。 etSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) { if (actionId == EditorInfo.IME_ACTION_SEARCH) { // 先隐藏键盘 ((InputMethodManager) etSearch.getContext().getSystemService(Context.INPUT_METHOD_SERVICE)) .hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); //搜索具体逻辑 Toast.makeText(getApplicationContext(),"已经跳转到"+etSearch.getText()+"界面",Toast.LENGTH_SHORT).show(); //保存历史记录 saveSearchHistory(String.valueOf(etSearch.getText())); return true; } return false; } });
接下来看下是如何保存的呢,采用键值对的方式,key为搜索时候的时间戳,value则为搜索时候的关键字,采用时间戳的做法相对于后期实现历史记录动态改变实现比较方便,按时间戳排序即可。所谓的动态改变就是原本为第二个的历史记录,我们再次搜索,会更改为最新的。但保存的时候要先做一步判断,查询一些是否存在,存在我们则删除,然后在put添加。下面代码就是采用遍历Map的效率高的一种方法entrySet(),entrySet是 键-值 对的集合,Set里面的类型是Map.Entry,
举个例子我们来看下entrySet()方法两种遍历:
public static void main(String[] args) { Map<String,String> map=new HashMap<String,String>(); map.put("1", "小王"); map.put("2", "小陈"); map.put("3", "小李"); /*方法一 :迭代程序*/ System.out.println("方法一:"); Iterator iterator=map.entrySet().iterator(); while(iterator.hasNext()){ Map.Entry<String, String> entry= (Entry<String, String>) iterator.next(); System.out.println("key:"+entry.getKey()+" value"+entry.getValue()); } /*方法二*/ System.out.println("方法二:"); for (Map.Entry<String, String> m : map.entrySet()) { System.out.println("key:"+m.getKey()+" value"+m.getValue()); } }
private void saveSearchHistory(String keyWords) { //保存之前要先查询sp中是否有该value的记录,有则删除.这样保证搜索历史记录不会有重复条目 Map<String, String> historys = (Map<String, String>) SearchHistoryUtils.getAll(getApplicationContext()); for (Map.Entry<String, String> entry : historys.entrySet()) { if(keyWords.equals(entry.getValue())){ SearchHistoryUtils.remove(getApplicationContext(),entry.getKey()); } } SearchHistoryUtils.put(getApplicationContext(), "" + mFormat.format(new Date()), keyWords);}
历史记录保存我们实现了,那么接下来就是展示的了,根据搜索的时间先后排序来展示的,当不存在历史记录时,隐藏footView,也就是清空历史记录那块布局。
private void showSearchHistory() { Map<String, String> hisAll = (Map<String, String>) SearchHistoryUtils.getAll(getApplicationContext()); //将key排序升序 Object[] keys = hisAll.keySet().toArray(); Arrays.sort(keys); int keyLeng = keys.length; //这里计算 如果历史记录条数是大于 可以显示的最大条数,则用最大条数做循环条件,防止历史记录条数-最大条数为负值,数组越界 int hisLeng = keyLeng > HISTORY_MAX ? HISTORY_MAX : keyLeng; for (int i = 1; i <= hisLeng; i++) { mResults.add(hisAll.get(keys[keyLeng - i])); } mListView.setAdapter(mAdapter); //如果size不为0 显示footerview mFooterView.setVisibility(0!=mResults.size()? View.VISIBLE:View.GONE);}
整个Activity
public class MainActivity extends AppCompatActivity {private EditText etSearch;private static final int MSG_SEARCH = 1;private static final int HISTORY_MAX = 5;//最多显示五条历史记录private Context mContext;private SimpleDateFormat mFormat;private ListView mListView;private View mFooterView;private MyAdapter mAdapter;private TextView tvCancel;List<String> mResults = new ArrayList<String>();protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initListener(); showSearchHistory();}private void initView() { etSearch=(EditText)findViewById(R.id.et_search); tvCancel= ((TextView) findViewById(R.id.tv_cancel)); mFormat = new SimpleDateFormat("yyyyMMddHHmmss"); mListView=(ListView)findViewById(R.id.listView); LayoutInflater layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE); mFooterView = layoutInflater.inflate(R.layout.footview, null); mListView.addFooterView(mFooterView); mAdapter=new MyAdapter(this);}private void initListener() { //监听软键盘输入法按下【搜索】事件。 etSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) { if (actionId == EditorInfo.IME_ACTION_SEARCH) { // 先隐藏键盘 ((InputMethodManager) etSearch.getContext().getSystemService(Context.INPUT_METHOD_SERVICE)) .hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); //搜索具体逻辑 Toast.makeText(getApplicationContext(),"已经跳转到"+etSearch.getText()+"界面",Toast.LENGTH_SHORT).show(); //搜索请求转交给函数去处理 saveSearchHistory(String.valueOf(etSearch.getText())); return true; } return false; } }); // 清空历史记录点击事件 mFooterView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { clearsearchHistory(); } }); //取消按钮点击事件 tvCancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { etSearch.setText(""); } });}/** */private void saveSearchHistory(String keyWords) { //保存之前要先查询sp中是否有该value的记录,有则删除.这样保证搜索历史记录不会有重复条目 Map<String, String> historys = (Map<String, String>) SearchHistoryUtils.getAll(getApplicationContext()); for (Map.Entry<String, String> entry : historys.entrySet()) { if(keyWords.equals(entry.getValue())){ SearchHistoryUtils.remove(getApplicationContext(),entry.getKey()); } } SearchHistoryUtils.put(getApplicationContext(), "" + mFormat.format(new Date()), keyWords);}private void showSearchHistory() { Map<String, String> hisAll = (Map<String, String>) SearchHistoryUtils.getAll(getApplicationContext()); //将key排序升序 Object[] keys = hisAll.keySet().toArray(); Arrays.sort(keys); int keyLeng = keys.length; //这里计算 如果历史记录条数是大于 可以显示的最大条数,则用最大条数做循环条件,防止历史记录条数-最大条数为负值,数组越界 int hisLeng = keyLeng > HISTORY_MAX ? HISTORY_MAX : keyLeng; for (int i = 1; i <= hisLeng; i++) { mResults.add(hisAll.get(keys[keyLeng - i])); } mListView.setAdapter(mAdapter); //如果size不为0 显示footerview mFooterView.setVisibility(0!=mResults.size()? View.VISIBLE:View.GONE);}private void clearsearchHistory() { SearchHistoryUtils.clear(this); //同时刷新历史记录显示页面 mResults = new ArrayList<>(); mListView.setAdapter(mAdapter); //mListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1,mResults)); //如果size不为0 显示footerview mFooterView.setVisibility(0!=mResults.size()?View.VISIBLE:View.GONE);}public class MyAdapter extends BaseAdapter { private LayoutInflater mInflater = null; private MyAdapter(Context context) { //根据context上下文加载布局,这里的是Demo17Activity本身,即this this.mInflater = LayoutInflater.from(context); } public int getCount() { return mResults.size(); } @Override public Object getItem(int i) { return mResults.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int i, View convertView, ViewGroup viewGroup) { ViewHolder holder; if(convertView == null) { holder = new ViewHolder(); convertView = mInflater.inflate(R.layout.lvitem, null); holder.title= ((TextView) convertView.findViewById(R.id.info)); convertView.setTag(holder); }else { holder = (ViewHolder)convertView.getTag(); } holder.title.setText(mResults.get(i)); return convertView; }} static class ViewHolder { public TextView title; }}
就是一个listView展示历史记录,其中有一个item布局,和一个footView布局
footview.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal" android:layout_width="match_parent"android:layout_height="match_parent"><ImageView android:id="@+id/ivClearAll" android:layout_width="15dp" android:layout_height="15dp" android:src="@mipmap/clear" android:layout_alignParentTop="true" android:layout_alignParentStart="true" android:layout_marginStart="177dp" android:layout_marginTop="16dp" /><TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="清空历史记录" android:textSize="15sp" android:layout_alignTop="@+id/ivClearAll" android:layout_toEndOf="@+id/ivClearAll" /></RelativeLayout>
lvitem.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/info" android:layout_marginTop="12dp" android:layout_marginLeft="35dp" android:layout_width="wrap_content" android:text="电子商务" android:textColor="#333333" android:layout_height="40dp" /></LinearLayout><View android:layout_width="match_parent" android:layout_height="1dp" android:background="#dfdfdf" /></LinearLayout>
工具类传送门 http://download.csdn.net/detail/u012896330/9728714
- Android 一般项目的 搜索功能 历史记录排序实现
- Android项目类似淘宝 电商 搜索功能,监听软键盘搜索事件,延迟自动搜索,以及时间排序的搜索历史记录的实现
- android 实现 搜索保存历史记录功能
- Android 类似淘宝 电商 搜索功能,监听软键盘搜索事件,延迟自动搜索,以及时间排序的搜索历史记录的实现
- Android实现搜索功能并本地保存搜索历史记录
- js实现搜索历史记录功能
- Android搜索功能的案例,本地保存搜索历史记录
- Android搜索功能的案例,本地保存搜索历史记录。
- Android搜索功能的案例,本地保存搜索历史记录
- 一般网站数据搜索的功能实现
- Android用AutoCompleteTextView实现搜索历史记录提示
- Android搜索功能的实现
- 使用EditText和SharedPreferences实现搜索历史记录提示功能
- iOS实现带历史记录功能的计算器
- 2-7实现用户的历史记录功能
- 我的Android进阶之旅------>Android用AutoCompleteTextView实现搜索历史记录提示
- 搜索实现 app 本地搜索效果,有历史记录的
- Android 实现ListView的A-Z字母排序和过滤搜索功能,实现汉字转成拼音
- Java学习博客和文章存档
- BZOJ 1588: [HNOI2002]营业额统计 (Treap/链表)
- 桶排序
- sqlite3.lib编译生成
- 利用UltraISO制作U盘启动盘
- Android 一般项目的 搜索功能 历史记录排序实现
- 每天一个linux命令(22):find 命令的参数详解
- redis数据类型详解
- 本地svn迁移到git
- 解决表单重复提交和分布式服务器验证码存放问题
- kubernetes1.5新特性:支持Photon卷插件
- POI Excel 单元格内容类型判断并取值
- fork()+pipe() --> 父子进程间通过管道通信
- javascript事件委托理解,jQuery .on()方法一步到位实现事件委托