RecyclerView + toolbar + searchview的实现搜索关联分为以下几步:
一,添加toolbar的布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/xxx"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:elevation="0dp">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/xxx"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:layout_scrollFlags="scroll|enterAlways"
app:navigationIcon="@drawable/xxx" />
</android.support.design.widget.AppBarLayout>
二,然后在menu文件中添加toolbar的searchview菜单,默认为图标,可以实现点击展开
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/xxx"
android:icon="@drawable/icon_search"
android:iconifiedByDefault="true"
android:imeOptions="actionSearch"
android:title="@string/xxx"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="collapseActionView|ifRoom" />
</menu>
这里需要把showAsAction设置为"collapseAction|ifRoom"
showAsAction属性共有五个值:ifRoom、never、always、withText、collapseActionView,可以混合使用。具体介绍如下:
ifRoom
会显示在Item中,但是如果已经有4个或者4个以上的Item时会隐藏在溢出列表中。当然个数并不仅仅局限于4个,依据屏幕的宽窄而定never
永远不会显示。只会在溢出列表中显示,而且只显示标题,所以在定义item的时候,最好把标题都带上。always
无论是否溢出,总会显示。withText
withText值示意Action bar要显示文本标题。
Action bar会尽可能的显示这个标题,但是,
如果图标有效并且受到Action bar空间的限制,文本标题有可能显示不全。collapseActionView
声明了这个操作视窗应该被折叠到一个按钮中,当用户选择这个按钮时,这个操作视窗展开。否则,这个操作视窗在默认的情况下是可见的,并且即便在用于不适用的时候,也要占据操作栏的有效空间。一般要配合ifRoom一起使用才会有效果。
imeOptions属性分别是:
actionDone 完成 对应 EditorInfo.IME_ACTION_DONE
actionGo 前进 对应 EditorInfo.IME_ACTION_GO
actionNext 下一项 对应 EditorInfo.IME_ACTION_NEXT
actionNone 无动作 对应 EditorInfo.IME_ACTION_NONE
actionPrevious 上一项 对应 EditorInfo.IME_ACTION_PREVIOUS
actionSearch 搜索 对应 EditorInfo.IME_ACTION_SEARCH
actionUnspecified 未指定 对应 EditorInfo.IME_ACTION_UNSPECIFIED
actionSend 发送 对应 EditorInfo.IME_ACTION_SEND
actionViewClass设置为系统或者v7库的searchview组件
三,Activity中的操作
使用线程池处理
private ScheduledExecutorService mScheduledExecutor = Executors.newScheduledThreadPool(10);
public ScheduledFuture<?> schedule(Runnable command, long delayTimeMills) {
return mScheduledExecutor.schedule(command, delayTimeMills, TimeUnit.MILLISECONDS);
}
绑定Toolbar,加载RecyclerView
setSupportActionBar(mToolbar);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
// 设置布局管理器
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(OrientationHelper.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.addItemDecoration(new DividerItemDecoration(
this, DividerItemDecoration.VERTICAL));
//加载数据
mSchedualDatas = xxxDBHelper.getxxxByType(xxx.xxx);
mAdapter = new xxx(this, mDatas);
mRecyclerView.setAdapter(mAdapter);
}
创建菜单,使用SearchView
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.clear();
getMenuInflater().inflate(R.menu.xxx, menu);
MenuItem menuItem = menu.findItem(R.id.xxx);
mSearchView = (SearchView) MenuItemCompat.getActionView(menuItem);//加载searchview
initSearchView();
return true;
}
为SearchView添加监听事件
public void initSearchView() {
mSearchView.setOnCloseListener(new SearchView.OnCloseListener() {
@Override
public boolean onClose() {
return true;
}
});
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if (TextUtils.isEmpty(newText)) {
return false;
}
showSearchTip(newText);
return true;
}
});
}
public void showSearchTip(String newText) {
schedule(new SearchTipThread(newText), 100);
}
创建线程处理耗时的查询操作
class SearchTipThread implements Runnable {
String newText;
public SearchTipThread(String newText) {
this.newText = newText;
}
public void run() {
if (newText.equals(mCurrentSearchTip)) {
return;
}
mCurrentSearchTip = newText;
mSchedualDatas = xxxDBHelper.getxxxByWord(newText, xxx);
mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_UPDATE));
}
}
创建Handler,在主线程更新UI. 这里需要Adapter的数据项产生变化后,调用notifyDataSetChanged才能更新RecyclerView.
private class UpdateHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE:
mAdapter.setDatas(mDatas);
mAdapter.notifyDataSetChanged();
break;
}
}
}
}
这样一个搜索页就做出来了.
四, Rxjava的改造
上面的例子里,线程池 handler什么的,逻辑太分散, 不妨用之前学得Rxjava改造一下:
protected void showSearchTip(String newText) {
Observable.just(newText)
.subscribeOn(Schedulers.io())
.map(new Function<String, List<xxx>>() {
@Override
public List<xxx> apply(String str) throws Exception {
if (!TextUtils.isEmpty(str) && str.equals(mCurrentSearchTip)) {
return null;
}
List<xxx> datas;
if (TextUtils.isEmpty(str)) {
datas = DBHelper.getxxxByType(xxx);
} else {
datas = DBHelper.gexxxByWord(str, xxx);
}
mCurrentSearchTip = str;
return datas;
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<List<xxx>>() {
@Override
public void accept(List<xxx> xxx) throws Exception {
getV().updateAdapter(xxx);
}
});
}
这下好看多了 : )
网友评论