這篇文章主要介紹安卓開發中常用的搜索框控件的使用。
爲第三方控件,需要添加依賴如下。
'com.quinny898.library.persistentsearch:library:1.1.0-SNAPSHOT'
同時因爲gradle默認倉庫爲jcenter,所以build一定會報錯。需要在另一個gradle腳本添加倉庫。(不是App的而是Project的build.gradle)
1.佈局使用
只要在主佈局中添加該空間即可。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
tools:context="com.zc.test.MainActivity"
android:orientation="vertical">
<com.quinny898.library.persistentsearch.SearchBox
android:layout_width="wrap_content"
android:id="@+id/searchbox"
android:layout_height="wrap_content"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<ListView
android:id="@+id/lv_history"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
<ListView
android:id="@+id/lv_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
<TextView
android:id="@+id/tv_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center_horizontal"
/>
</LinearLayout>
2.代碼實現
package com.zc.test;
/**
* Created by 16957 on 2018/11/18.
*/
import android.content.Context;
import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import com.quinny898.library.persistentsearch.SearchBox;
import com.quinny898.library.persistentsearch.SearchResult;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
//上下文
private Context mContext;
//搜索框控件,可以自定義style
private SearchBox sbSearch;
//底部結果統計控件
private TextView tvBottom;
//數據列表
private List<String> listSearch;
//結果列表
private List<String> listResult;
//歷史列表控件
private ListView mHistory ;
//搜索結果列表控件
private ListView mSearchResult ;
//底部結果控件
private TextView bottom;
//兩個繼承BaseAdapter的適配器,搜索歷史sf本地保存
private SearchAdapter mResultAdapter ;
private HistoryAdapter mHistoryAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
bindViews();
}
@Override
protected void onResume() {
super.onResume();
initData();
init();
initHistory();
updateBottom();
}
private void initData() {
//本地可供檢索數據獲取,每次resume就要重新渲染
listSearch = new ArrayList<>();
listSearch.add("123");
listSearch.add("1234");
listSearch.add("12345");
}
private void bindViews() {
mSearchResult = (ListView) findViewById(R.id.lv_content);
sbSearch = (SearchBox) findViewById(R.id.searchbox);
tvBottom = (TextView) findViewById(R.id.tv_bottom);
mHistory = (ListView) findViewById(R.id.lv_history);
bottom = (TextView) findViewById(R.id.tv_bottom);
}
public void init(){
//結果的初始化
listResult = new ArrayList<>();
mResultAdapter = new SearchAdapter(MainActivity.this, listResult);
mSearchResult.setAdapter(mResultAdapter);
mSearchResult.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
});
//搜索框的初始化
sbSearch.enableVoiceRecognition(this);
sbSearch.setMenuListener(new SearchBox.MenuListener(){
@Override
public void onMenuClick() {
finish();
}
});
sbSearch.setSearchListener(new SearchBox.SearchListener(){
@Override
public void onSearchOpened() {
//Use this to tint the screen
}
@Override
public void onSearchClosed() {
//Use this to un-tint the screen
}
@Override
public void onSearchTermChanged(String term) {
//搜索框內容修改就進行搜索,但只要點擊搜索按鈕纔會加入搜索歷史
search(term);
updateBottom();
if(listResult.size()==0){
mHistory.setVisibility(View.VISIBLE);
}else {
mHistory.setVisibility(View.GONE);
}
}
@Override
public void onSearch(String searchTerm) {
search(searchTerm);
saveHistory(searchTerm);
initHistory();
updateBottom();
}
@Override
public void onResultClick(SearchResult result) {
//React to a result being clicked
}
@Override
public void onSearchCleared() {
//Called when the clear button is clicked
}
});
}
private void initHistory(){
final List<String> history = getHistory();
mHistoryAdapter = new HistoryAdapter(MainActivity.this,history);
mHistory.setAdapter(mHistoryAdapter);
mHistory.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
sbSearch.populateEditText(history.get(position));
sbSearch.setSearchString(history.get(position));
}
});
}
private void search(String newText){
//若搜索內容爲空
if(newText.isEmpty()){
listResult.clear();
}
else{
for (String node : listSearch) {
//在數據集遍歷搜索
if (node.contains(newText)) {
if(listResult.indexOf(node)==-1) {
//如果結果集不含有它(爲了防止結果重複)
listResult.add(node);
}
}else{
//搜索內容搜索不到相關 檢測是否之前有加入結果集 有則刪除
if(listResult.indexOf(node)!=-1) {
listResult.remove(node);
}
}
}
}
mResultAdapter.notifyDataSetChanged();
}
private ArrayList<String> getHistory() {
SharedPreferences reader = getSharedPreferences("history", MODE_PRIVATE);
String data = reader.getString("data_history", "");
ArrayList<String> history = new ArrayList<>();
String [] get= data.split("\\|");
for( String str:get){
if(! history.contains(str) && !str.isEmpty()){
history.add(str);
}
}
return history;
}
private void saveHistory(String s){
StringBuilder sb = new StringBuilder();
SharedPreferences.Editor editor = getSharedPreferences("history",MODE_PRIVATE).edit();
for (String str: getHistory()){
sb.append(str);
sb.append("|");
}
sb.append(s);
editor.putString("data_history",sb.toString());
editor.apply();
}
private void updateBottom(){
if(sbSearch.getSearchText().trim().isEmpty()){
bottom.setVisibility(View.GONE);
return;
}
tvBottom.setVisibility(View.VISIBLE);
tvBottom.setText("找到了 "+ listResult.size() +" 條記錄");
}
}
3.效果演示
這個項目只是個測試代碼,所以組件渲染和事件處理是存在很多bug的,歡迎指正。
項目github地址:https://github.com/luanshiyinyang/TestForPersistentSearch