本文主要介绍SearchView的使用、即时搜索提示功能的实现,以及一些设置。
具体代码可见SearchViewDemo@Github,可实现效果如下:
Demo APK 可以方便的查看效果,在各大应用商店搜索 trinea android 下载即可,如:Google Play。
1. layout文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <SearchView android:id="@+id/search_view" android:layout_width="match_parent" android:layout_height="match_parent" android:iconifiedByDefault="true" android:inputType="textCapWords" android:imeOptions="actionSearch" android:queryHint="" /> </RelativeLayout> |
xml中主要配置有四个属性,如下:
android:iconifiedByDefault表示搜索图标是否在输入框内。true效果更加
android:imeOptions设置IME options,即输入法的回车键的功能,可以是搜索、下一个、发送、完成等等。这里actionSearch表示搜索
android:inputType输入框文本类型,可控制输入法键盘样式,如numberPassword即为数字密码样式
android:queryHint输入框默认文本
2. java部分代码
SearchView几个主要函数
setOnCloseListener(SearchView.OnCloseListener listener)表示点击取消按钮listener,默认点击搜索输入框
setOnQueryTextListener(SearchView.OnQueryTextListener listener)表示输入框文字listener,包括public boolean onQueryTextSubmit(String query)开始搜索listener,public boolean onQueryTextChange(String newText)输入框内容变化listener,两个函数,下面代码包含了如何利用延迟执行实现搜索提示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
package cn.trinea.android.demo; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import android.app.ActionBar; import android.app.ActionBar.LayoutParams; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.WindowManager; import android.widget.SearchView; import android.widget.SearchView.OnCloseListener; import android.widget.Toast; public class SearchViewDemo extends Activity { private SearchView searchView; private Context context; private MyHandler handler; // schedule executor private ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(10); private String currentSearchTip; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.search_view_demo); context = getApplicationContext(); handler = new MyHandler(); ActionBar actionBar = getActionBar(); actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_CUSTOM); setTitle(" "); LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); View customActionBarView = inflater.inflate(R.layout.search_view_demo_title, null); searchView = (SearchView)customActionBarView.findViewById(R.id.search_view); searchView.setIconified(false); searchView.setOnCloseListener(new OnCloseListener() { @Override public boolean onClose() { // to avoid click x button and the edittext hidden return true; } }); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { public boolean onQueryTextSubmit(String query) { Toast.makeText(context, "begin search", Toast.LENGTH_SHORT).show(); return true; } public boolean onQueryTextChange(String newText) { if (newText != null && newText.length() > 0) { currentSearchTip = newText; showSearchTip(newText); } return true; } }); LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.RIGHT); actionBar.setCustomView(customActionBarView, params); // show keyboard getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); } public void showSearchTip(String newText) { // excute after 500ms, and when excute, judge current search tip and newText schedule(new SearchTipThread(newText), 500); } class SearchTipThread implements Runnable { String newText; public SearchTipThread(String newText){ this.newText = newText; } public void run() { // keep only one thread to load current search tip, u can get data from network here if (newText != null && newText.equals(currentSearchTip)) { handler.sendMessage(handler.obtainMessage(1, newText + " search tip")); } } } public ScheduledFuture<?> schedule(Runnable command, long delayTimeMills) { return scheduledExecutor.schedule(command, delayTimeMills, TimeUnit.MILLISECONDS); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: { onBackPressed(); return true; } } return false; } private class MyHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: Toast.makeText(context, (String)msg.obj, Toast.LENGTH_SHORT).show(); break; } } } } |
上面代码在onQueryTextChange函数即输入框内容每次变化时将一个数据获取线程SearchTipThread放到ScheduledExecutorService中,500ms后执行,在线程执行时判断当前输入框内容和要搜索内容,若相等则继续执行,否则直接返回,避免不必要的数据获取和多个搜索提示同时出现。
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
| WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
表示默认输入法弹出
编辑框内容为空点击取消的x按钮,编辑框收缩,可在onClose中返回true
1 2 3 4 5 6 7 |
searchView.setOnCloseListener(new OnCloseListener() { @Override public boolean onClose() { return true; } }); |
searchView.onActionViewExpanded();表示在内容为空时不显示取消的x按钮,内容不为空时显示.
searchView.setSubmitButtonEnabled(true);编辑框后显示search按钮,个人建议用android:imeOptions=”actionSearch”代替。
隐藏输入法键盘
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
InputMethodManager inputMethodManager; inputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); private void hideSoftInput() { if (inputMethodManager != null) { View v = SearchActivity.this.getCurrentFocus(); if (v == null) { return; } inputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); searchView.clearFocus(); } } |
其中SearchActivity为Activity的类名
Thank you
实现一个智能提示功能需要ajax、数据库、jsp/php、算法等很多知识,
如果数据量大,还需要特殊优化
一个小功能,花费太大精力很不划算
我使用了92find.c-o-m的搜索框智能提示功能托管服务,
只要一行javascript代码就可以实现百度、淘宝搜索框提示的全部功能
比如:汉字拼音匹配、拼音前缀匹配、模糊搜索、智能容错,还可以自定义提示词汇及其排序权重
花五分钟我的网站就可以部署同百度、淘宝一样强大好用的输入提示功能
同时兼容IE、Firefox、Safari、Chrome、Opera各种浏览器
兼容ios、Android、Windows
给延迟搜索提个小建议。
比如我清空了SearchView中的文字,本来根据Listener中的判断要执行其他操作(比如显示一个新的fragmentA),结果因为操作很快,500ms的那个指令在前者执行完后才到达(比如显示一个fragmentB),就把刚才的在SearchView中监听到无文字时的操作给覆盖了。这时候可以加个boolean来判断下,如果为空就不允许再在handler中执行其他指令。
是的,代码里有一部分后来没有提交,在返回处理时同样需要判断
if (currentSearchTip != null && currentSearchTip.equals(newText))
请问左边的返回箭头是如何设置的。
searchView.onActionViewExpanded();表示在内容为空时不显示取消的x按钮,内容不为空时显示.我发现没有这段代码,x按钮默认就是有内容才显示的。这个不对啊,mSearchView.onActionViewCollapsed(); mSearchView.onActionViewExpanded();它们分别是设置SearchView默认是展开还是收缩的啊
现在做的项目正好有这个需求,受教了~
没有见到ListUtils这个类啊
https://github.com/Trinea/android-common
https://github.com/Trinea/android-demo