布局如下,通过一个RecyclerView控制显示三种情况的显示
<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"
tools:context=".MainActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/material_primary"
android:theme="@style/ToolBarStyle"
app:popupTheme="@style/Theme.AppCompat.Light">
</android.support.v7.widget.Toolbar>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/toolbar"
android:background="@color/material_icons"
android:scrollbars="none"/>
<TextView
android:id="@+id/tv_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25sp"
android:textColor="@color/material_red_a700"
android:text="Open The SearchView"
android:layout_centerInParent="true"/>
</RelativeLayout>
①界面初始化,简单设置下Toolbar,RecyclerView ,
mHistoryOrAllSearchList用于存放历史或联想词;mHotSearchList用于存放热词
SharedPreUtil.readString(Constant.OPENTIME).isEmpty()用来模拟版本变化更新数据库
更新数据库会将上版本的热词和联想词删除,涉及到大数据量,所以开线程操作mKeywordsTableDao.getSession().runInTx
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
if (mToolbar == null) {
return;
}
mToolbar.setTitle(R.string.app_name);
setSupportActionBar(mToolbar);
RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
StaggeredGridLayoutManager mManager = new StaggeredGridLayoutManager(2,
StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mManager);
mRecyclerView.addItemDecoration(new SpacesItemDecoration(5));
mAdapter = new SearchAdapter(this);
mAdapter.setItemClickLitener(this);
mRecyclerView.setAdapter(mAdapter);
mHistoryOrAssociativeSearchList = new ArrayList<>();
mHotSearchList = new ArrayList<>();
mKeywordsTableDao = getSearchKeywordsTableDao(mKeywordsTableDao);
if (SharedPreUtil.readString(Constant.OPENTIME).isEmpty()) {
// 词库版本有更新才去更新数据库的热词和练习词
final List<SearchKeywords> keywordses = new ArrayList<>();
// 热词
keywordses.add(new SearchKeywords("women", 12, -1, Constant.SEARCH_KEYWORDS_HOT));
keywordses.add(new SearchKeywords("men", 10, -1, Constant.SEARCH_KEYWORDS_HOT));
keywordses.add(new SearchKeywords("beauty", 16, -1, Constant.SEARCH_KEYWORDS_HOT));
keywordses.add(new SearchKeywords("makeup", 2, -1, Constant.SEARCH_KEYWORDS_HOT));
keywordses.add(new SearchKeywords("clothes", 6, -1, Constant.SEARCH_KEYWORDS_HOT));
// 联想词
keywordses.add(new SearchKeywords("women", 12, -1,
Constant.SEARCH_KEYWORDS_ASSOCIATIVE));
keywordses.add(new SearchKeywords("men", 10, -1,
Constant.SEARCH_KEYWORDS_ASSOCIATIVE));
keywordses.add(new SearchKeywords("beauty", 16, -1,
Constant.SEARCH_KEYWORDS_ASSOCIATIVE));
keywordses.add(new SearchKeywords("makeup", 2, -1,
Constant.SEARCH_KEYWORDS_ASSOCIATIVE));
keywordses.add(new SearchKeywords("clothes", 6, -1,
Constant.SEARCH_KEYWORDS_ASSOCIATIVE));
keywordses.add(new SearchKeywords("cute", 26, -1,
Constant.SEARCH_KEYWORDS_ASSOCIATIVE));
keywordses.add(new SearchKeywords("watch", 32, -1,
Constant.SEARCH_KEYWORDS_ASSOCIATIVE));
keywordses.add(new SearchKeywords("sexy", 16, -1,
Constant.SEARCH_KEYWORDS_ASSOCIATIVE));
mKeywordsTableDao.getSession().runInTx(new Runnable() {
@Override
public void run() {
// 避免数据太多阻塞主线程
// 清除旧版本的热词和联想词
clearTopAndAssociativeSearchKeyWords();
insertSearchKeywordsToDb(keywordses);
}
});
SharedPreUtil.writeString(Constant.OPENTIME, System.currentTimeMillis() + "");
}
}
②RecyclerView适配器的设计
会有三种视图模式,暴露方法获取当前模式和设置当前模式
// 历史和热词模式
public static final int MODE_KEYWORDS_REVIEW = 0;
// 搜索结果模式
public static final int MODE_RESULT = 1;
// 联想匹配模式
public static final int MODE_KEYWORDS_MATCH = 2;
public int getCurrentMode() {
return mCurrentMode;
}
public void setCurrentMode(int currentMode) {
this.mCurrentMode = currentMode;
}
private int mCurrentMode;
填充数据有两个成员变量
/** * 搜索热词 */
private List<String> mHotSearchList;
public List<String> getHotSearchList() {
return mHotSearchList;
}
public void setHotSearchList(List<String> allSearchList) {
this.mHotSearchList = allSearchList;
}
/** * 搜索历史,或者是匹配的单词 */
private List<String> mHistoryOrAssociativeSearchList;
public List<String> getHistoryOrAssociativeSearchList() {
return mHistoryOrAssociativeSearchList;
}
public void setHistoryOrAssociativeSearchList(List<String> historyOrAssociativeSearchList) {
this.mHistoryOrAssociativeSearchList = historyOrAssociativeSearchList;
}
有四种View类型:
①VIEW_TYPE_TIP ,标题,在显示历史和热搜的时候为标识类型;显示搜索结果的时候标识搜索结果的搜索单词
②VIEW_TYPE_KEYWORD ,搜索单词
③VIEW_TYPE_RESULT ,搜索结果
④VIEW_TYPE_DELETE_HISTORY,一键清空的布局
private final int VIEW_TYPE_TIP = 0;
private final int VIEW_TYPE_KEYWORD = 1;
private final int VIEW_TYPE_RESULT = 2;
private final int VIEW_TYPE_DELETE_HISTORY = 3;
@Override
public SearchAdapter.RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerViewHolder viewHolder;
switch (viewType) {
case VIEW_TYPE_TIP:
viewHolder = new RecyclerViewHolder
(LayoutInflater.from(mContext).inflate(R.layout.item_search_head, parent, false));
return viewHolder;
case VIEW_TYPE_KEYWORD:
View view LayoutInflater.from(mContext).inflate(R.layout.item_search,
parent, false);
viewHolder = new RecyclerViewHolder(view);
view.findViewById(R.id.iv_delete).setOnClickListener(this);
view.findViewById(R.id.ll_search).setOnClickListener(this);
return viewHolder;
case VIEW_TYPE_RESULT:
viewHolder = new RecyclerViewHolder
(LayoutInflater.from(mContext).inflate(R.layout.item_search_result, parent, false));
return viewHolder;
case VIEW_TYPE_DELETE_HISTORY:
View view1 =
LayoutInflater.from(mContext).inflate(R.layout.item_search_delete_history, parent,
false);
viewHolder = new RecyclerViewHolder(view1);
view1.findViewById(R.id.tv_clear_history).setOnClickListener(this);
return viewHolder;
}
return null;
}
@Override
public void onBindViewHolder(SearchAdapter.RecyclerViewHolder holder, int position) {
switch (getItemViewType(position)) {
case VIEW_TYPE_TIP:
StaggeredGridLayoutManager.LayoutParams lp =
(StaggeredGridLayoutManager.LayoutParams) holder.mHeadLayout.getLayoutParams();
lp.setFullSpan(true);
if (mCurrentMode != MODE_RESULT) {
// 历史和热词模式,位置不为0,说明同时存在历史和热搜,标配自然是“Hot”,如果等于0,
holder.mTitleText.setText(position != 0 ? "Hot" : mHistoryExist ?
"History" : "Hot");
} else {
// 结果模式,搜索单词
holder.mTitleText.setText("word: " + mSearchWord);
}
break;
case VIEW_TYPE_DELETE_HISTORY:
// 不用做任何事,只是一个点击事件清空历史
StaggeredGridLayoutManager.LayoutParams lp3 =
(StaggeredGridLayoutManager.LayoutParams) ((ViewGroup)
holder.mClearHistoryText.getParent()).getLayoutParams();
lp3.setFullSpan(true);
break;
case VIEW_TYPE_KEYWORD:
StaggeredGridLayoutManager.LayoutParams lp1 =
(StaggeredGridLayoutManager.LayoutParams) ((ViewGroup)
holder.mSearchKeyWordText.getParent()).getLayoutParams();
lp1.setFullSpan(true);
if (mCurrentMode == MODE_KEYWORDS_MATCH) {
// 联想匹配模式
if (mHistoryExist) {
holder.mDeleteImg.setVisibility(View.GONE);
holder.mSearchKeyWordText.setText(mHistoryOrAssociativeSearchList.get(position));
holder.mSearchLayout.setTag(position);
}
} else if (mCurrentMode == MODE_KEYWORDS_REVIEW) {
// 历史和热搜模式
if (mHistoryExist) {
// 存在历史数据
if (position < mHistoryOrAssociativeSearchList.size() + 1) {
// 删除按钮设置为可见,历史可以删除
holder.mSearchKeyWordText
.setText(mHistoryOrAssociativeSearchList.get(position - 1));
holder.mDeleteImg.setVisibility(View.VISIBLE);
holder.mDeleteImg.setTag(position - 1);
holder.mSearchLayout.setTag(position - 1);
} else {
// 设置热搜数据
// DebugLog.e("position=" + position);
holder.mDeleteImg.setVisibility(View.GONE);
holder.mSearchKeyWordText.setText(mHotSearchList.get(position - 3 -
mHistoryOrAssociativeSearchList.size()));
holder.mSearchLayout.setTag(position - 3);
}
} else if (mHotExist) {
// 只存在热搜数据
holder.mDeleteImg.setVisibility(View.GONE);
holder.mSearchKeyWordText.setText(mHotSearchList.get(position - 1));
holder.mSearchLayout.setTag(position - 1);
}
}
break;
case VIEW_TYPE_RESULT:
// 搜索结果
StaggeredGridLayoutManager.LayoutParams lp2 =
(StaggeredGridLayoutManager.LayoutParams) ((ViewGroup)
holder.mResultText.getParent()).getLayoutParams();
lp2.setFullSpan(true);
holder.mResultText.setText("The search word is " + mSearchWord);
break;
}
}
@Override
public int getItemViewType(int position) {
if (mCurrentMode == MODE_KEYWORDS_REVIEW) {
int hotTitlePosition = 0;
if (mHistoryExist && mHotExist) {
// 同时存在的时候才有第二个标题
hotTitlePosition = mHistoryOrAssociativeSearchList.size() + 1 + 1;
}
if (mHistoryExist && position == mHistoryOrAssociativeSearchList.size() + 1) {
// 有历史记录存在,历史纪录后面是一个一键情空历史按钮
return VIEW_TYPE_DELETE_HISTORY;
}
return position == 0 || position == hotTitlePosition ? VIEW_TYPE_TIP :
VIEW_TYPE_KEYWORD;
} else if (mCurrentMode == MODE_KEYWORDS_MATCH) {
return VIEW_TYPE_KEYWORD;
} else if (mCurrentMode == MODE_RESULT) {
return position == 0 ? VIEW_TYPE_TIP : VIEW_TYPE_RESULT;
}
return -1;
}
boolean mHistoryExist;
boolean mHotExist;
@Override
public int getItemCount() {
int itemCount = 0;
if (mCurrentMode == MODE_KEYWORDS_REVIEW) {
mHistoryExist = mHistoryOrAssociativeSearchList != null &&
mHistoryOrAssociativeSearchList.size() > 0;
mHotExist = mHotSearchList != null && mHotSearchList.size() > 0;
if (mHistoryExist) {
// 存在历史,加个历史的标题
itemCount += mHistoryOrAssociativeSearchList.size() + 1;
// 加个一键清空历史的按钮
itemCount += 1;
if (mHotExist) {
// 存在热搜,加个热搜的标题
itemCount += mHotSearchList.size() + 1;
}
} else {
// 不存在历史
if (mHotExist) {
// 存在热搜,加个热搜的标题
itemCount += mHotSearchList.size() + 1;
}
}
} else if (mCurrentMode == MODE_KEYWORDS_MATCH) {
mHistoryExist = mHistoryOrAssociativeSearchList != null &&
mHistoryOrAssociativeSearchList.size() > 0;
if (mHistoryExist) {
itemCount += mHistoryOrAssociativeSearchList.size();
}
} else if (mCurrentMode == MODE_RESULT) {
// 结果是标题加text显示搜索词语
return itemCount += 2;
}
return itemCount;
}
菜单的设置
private MenuItem mSearchItem;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
mSearchItem = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(mSearchItem);
final SearchView.SearchAutoComplete searchEditText = (SearchView.SearchAutoComplete)
searchView.findViewById(R.id.search_src_text);
searchView.setQueryHint("Search");
// 将搜索按钮放到搜索输入框的外边
searchView.setIconifiedByDefault(false);
// 设置输入框底部的横线的颜色
View searchPlate = searchView.findViewById(android.support.v7.appcompat.R.id.search_plate);
searchPlate.setBackgroundResource(R.mipmap.ic_searchview_plate);
searchPlate.getBackground().setColorFilter(getResources().getColor(R.color.material_a
ccent), PorterDuff.Mode.SRC_ATOP);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
// 提交查询条件
DebugLog.e("提交查询:" + query);
submitKeywords(query);
searchEditText.setText("");
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
// 这里做搜索联想
if (mAdapter.getCurrentMode() == SearchAdapter.MODE_RESULT) {
DebugLog.e("搜索结果模式,不做处理");
return true;
}
if (newText.isEmpty()) {
DebugLog.e("搜索为空,显示历史和热词");
showHistoryAndHotKeywords();
} else {
DebugLog.e("搜索词不为空,显示匹配");
mHotSearchList.clear();
mHistoryOrAssociativeSearchList.clear();
insertMatchKeywordsToRecycleView(mHistoryOrAssociativeSearchList, newText);
mAdapter.setCurrentMode(SearchAdapter.MODE_KEYWORDS_MATCH);
mAdapter.setHistoryOrAssociativeSearchList(mHistoryOrAssociativeSearchList);
mAdapter.notifyDataSetChanged();
}
return true;
}
});
return true;
}
点击事件的处理
/** * 提交结果 * * @param query */
private void submitKeywords(String query) {
mAdapter.setCurrentMode(SearchAdapter.MODE_RESULT);
final SearchKeywords keywords = new SearchKeywords(query, -1, System.currentTimeMillis(),
Constant.SEARCH_KEYWORDS_HISTORY);
insertHistorySearchKeywordsToDb(keywords);
hideKeybord(MainActivity.this, MainActivity.this.getCurrentFocus());
mAdapter.setSearchWord(query);
mAdapter.notifyDataSetChanged();
MenuItemCompat.collapseActionView(mSearchItem);
}
/** * 显示历史和热词 */
private void showHistoryAndHotKeywords() {
mAdapter.setCurrentMode(SearchAdapter.MODE_KEYWORDS_REVIEW);
mHotSearchList.clear();
mHistoryOrAssociativeSearchList.clear();
insertKeywordsToRecyclerView(mHistoryOrAssociativeSearchList,
Constant.SEARCH_KEYWORDS_HISTORY);
insertKeywordsToRecyclerView(mHotSearchList, Constant.SEARCH_KEYWORDS_HOT);
mAdapter.setHistoryOrAssociativeSearchList(mHistoryOrAssociativeSearchList);
mAdapter.setHotSearchList(mHotSearchList);
mAdapter.notifyDataSetChanged();
}
@Override
public void onItemClick(View view, int position) {
switch (view.getId()) {
case R.id.iv_delete:
hideKeybord(MainActivity.this, MainActivity.this.getCurrentFocus());
DebugLog.e("删除历史: " + mHistoryOrAssociativeSearchList.get(position));
clearSearchKeyWords(mHistoryOrAssociativeSearchList.get(position));
mHistoryOrAssociativeSearchList.remove(position);
mAdapter.notifyDataSetChanged();
break;
case R.id.ll_search:
boolean historyExist = mHistoryOrAssociativeSearchList != null &&
mHistoryOrAssociativeSearchList.size() > 0;
boolean hotExist = mHotSearchList != null && mHotSearchList.size() > 0;
String keyword = null;
if (historyExist) {
if (position >= mHistoryOrAssociativeSearchList.size()) {
// 点击的是热搜
keyword = mHotSearchList.get(position -
mHistoryOrAssociativeSearchList.size());
DebugLog.e("点击的是热搜: " + keyword);
} else {
keyword = mHistoryOrAssociativeSearchList.get(position);
if (mAdapter.getCurrentMode() == SearchAdapter.MODE_KEYWORDS_MATCH) {
DebugLog.e("点击的是联想的匹配: " + keyword);
} else if (mAdapter.getCurrentMode() == SearchAdapter.MODE_KEYWORDS_REVIEW) {
DebugLog.e("点击的是历史: " + keyword);
}
}
} else if (hotExist) {
keyword = mHotSearchList.get(position);
DebugLog.e("点击的是热搜: " + keyword);
}
if (keyword != null) {
submitKeywords(keyword);
MenuItemCompat.collapseActionView(mSearchItem);
}
break;
case R.id.tv_clear_history:
DebugLog.e("点击了一键清空历史");
clearHisotySearchKeyWords();
mHistoryOrAssociativeSearchList.clear();
mAdapter.setCurrentMode(SearchAdapter.MODE_KEYWORDS_REVIEW);
mAdapter.notifyDataSetChanged();
break;
}
}
可能说得不是很清楚,附上demo,跑一下,看下源码估计就差不多了>_<
SearchView+GreenDao搜索功能实现