1. 程式人生 > 程式設計 >Android本地實現搜尋歷史記錄

Android本地實現搜尋歷史記錄

本文例項為大家分享了Android本地實現搜尋歷史記錄的具體程式碼,供大家參考,具體內容如下

一.自定義搜尋歷史記錄

本地實現搜尋歷史記錄有很多種方法,下面不多說了,我們來用SQLite來實現此功能,直接上完整程式碼:點選下載原始碼

效果一:

Android本地實現搜尋歷史記錄

Android本地實現搜尋歷史記錄

效果二:

Android本地實現搜尋歷史記錄

1.MainActivity主函式

package com.example.administrator.searchapplication;
 
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
 
import java.util.ArrayList;
import java.util.List;
 
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
 
 private EditText searchContentEt;
 private SearchRecordsAdapter recordsAdapter;
 private View recordsHistoryView;
 private ListView recordsListLv;
 private TextView clearAllRecordsTv;
 private LinearLayout searchRecordsLl;
 
 private List<String> searchRecordsList;
 private List<String> tempList;
 private RecordsDao recordsDao;
 private TextView tv_history;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 initView();
 initData();
 bindAdapter();
 initListener();
 }
 private void initView() {
// setHideHeader();
 initRecordsView();
 
 searchRecordsLl = (LinearLayout) findViewById(R.id.search_content_show_ll);
 searchContentEt = (EditText) findViewById(R.id.input_search_content_et);
 tv_history = (TextView) findViewById(R.id.tv_history);
 
 //新增搜尋view
 searchRecordsLl.addView(recordsHistoryView);
 
 }
 
 //初始化搜尋歷史記錄View
 private void initRecordsView() {
 recordsHistoryView = LayoutInflater.from(this).inflate(R.layout.search_lishi,null);
 //顯示歷史記錄lv
 recordsListLv = (ListView) recordsHistoryView.findViewById(R.id.search_records_lv);
 //清除搜尋歷史記錄
 clearAllRecordsTv = (TextView) recordsHistoryView.findViewById(R.id.clear_all_records_tv);
 }
 
 
 private void initData() {
 recordsDao = new RecordsDao(this);
 searchRecordsList = new ArrayList<>();
 tempList = new ArrayList<>();
 tempList.addAll(recordsDao.getRecordsList());
 
 reversedList();
 //第一次進入判斷資料庫中是否有歷史記錄,沒有則不顯示
 checkRecordsSize();
 }
 
 
 private void bindAdapter() {
 recordsAdapter = new SearchRecordsAdapter(this,searchRecordsList);
 recordsListLv.setAdapter(recordsAdapter);
 }
 
 private void initListener() {
 clearAllRecordsTv.setOnClickListener(this);
 searchContentEt.setOnEditorActionListener(new TextView.OnEditorActionListener() {
 
  @Override
  public boolean onEditorAction(TextView v,int actionId,KeyEvent event) {
  if (actionId == EditorInfo.IME_ACTION_SEARCH) {
   if (searchContentEt.getText().toString().length() > 0) {
 
   String record = searchContentEt.getText().toString();
 
   //判斷資料庫中是否存在該記錄
//   if (!recordsDao.isHasRecord(record)) {
//    tempList.add(record);
//   }
   //將搜尋記錄儲存至資料庫中
   recordsDao.addRecords(record);
//   reversedList();
//   checkRecordsSize();
//   recordsAdapter.notifyDataSetChanged();
   Toast.makeText(MainActivity.this,"11",Toast.LENGTH_SHORT).show();
   //根據關鍵詞去搜索
 
   } else {
   Toast.makeText(MainActivity.this,"搜尋內容不能為空",Toast.LENGTH_SHORT).show();
   }
  }
  return false;
  }
 });
 
 //根據輸入的資訊去模糊搜尋
 searchContentEt.addTextChangedListener(new TextWatcher() {
  @Override
  public void beforeTextChanged(CharSequence s,int start,int count,int after) {
 
  }
 
  @Override
  public void onTextChanged(CharSequence s,int before,int count) {
 
  }
 
  @Override
  public void afterTextChanged(Editable s) {
  if (s.toString().trim().length() == 0) {
   tv_history.setText("搜尋歷史");
  } else {
   tv_history.setText("搜尋結果");
  }
  String tempName = searchContentEt.getText().toString();
  tempList.clear();
  tempList.addAll(recordsDao.querySimlarRecord(tempName));
  reversedList();
  checkRecordsSize();
  recordsAdapter.notifyDataSetChanged();
  }
 });
 //歷史記錄點選事件
 recordsListLv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  @Override
  public void onItemClick(AdapterView<?> parent,View view,int position,long id) {
  //將獲取到的字串傳到搜尋結果介面
  //點選後搜尋對應條目內容
//  searchContentEt.setText(searchRecordsList.get(position));
  Toast.makeText(MainActivity.this,searchRecordsList.get(position)+"",Toast.LENGTH_SHORT).show();
  searchContentEt.setSelection(searchContentEt.length());
  }
 });
 }
 
 //當沒有匹配的搜尋資料的時候不顯示歷史記錄欄
 private void checkRecordsSize(){
 if(searchRecordsList.size() == 0){
  searchRecordsLl.setVisibility(View.GONE);
 }else{
  searchRecordsLl.setVisibility(View.VISIBLE);
 }
 }
 
 @Override
 public void onClick(View v) {
 switch (v.getId()){
  //清空所有歷史資料
  case R.id.clear_all_records_tv:
  tempList.clear();
  reversedList();
  recordsDao.deleteAllRecords();
  recordsAdapter.notifyDataSetChanged();
  searchRecordsLl.setVisibility(View.GONE);
  searchContentEt.setHint("請輸入你要搜尋的內容");
  break;
 }
 }
 
 //顛倒list順序,使用者輸入的資訊會從上依次往下顯示
 private void reversedList(){
 searchRecordsList.clear();
 for(int i = tempList.size() - 1 ; i >= 0 ; i --) {
  searchRecordsList.add(tempList.get(i));
 }
 }
}

2.SearchRecordsAdapter介面卡

package com.example.administrator.searchapplication;
 
/**
 * Created by Administrator on 2018/2/11.
 */
 
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
 
import java.util.List;
 
/**
 * Created by 05 on 2016/7/27.
 */
public class SearchRecordsAdapter extends BaseAdapter {
 
 private Context context;
 private List<String> searchRecordsList;
 private LayoutInflater inflater;
 
 public SearchRecordsAdapter(Context context,List<String> searchRecordsList) {
 this.context = context;
 this.searchRecordsList = searchRecordsList;
 inflater = LayoutInflater.from(context);
 }
 
 @Override
 public int getCount() {
 //設定listView的顯示條目數量為5
 return searchRecordsList.size() > 5 ? 5 : searchRecordsList.size();
 }
 
 @Override
 public Object getItem(int position) {
 return searchRecordsList.size() == 0 ? null : searchRecordsList.get(position);
 }
 
 @Override
 public long getItemId(int position) {
 return position;
 }
 
 @Override
 public View getView(int position,View convertView,ViewGroup parent) {
 ViewHolder viewHolder;
 if(null == convertView){
  viewHolder = new ViewHolder();
  convertView = inflater.inflate(R.layout.list_item,null);
  viewHolder.recordTv = (TextView) convertView.findViewById(R.id.search_content_tv);
 
  convertView.setTag(viewHolder);
 }else{
  viewHolder = (ViewHolder) convertView.getTag();
 }
 
 String content = searchRecordsList.get(position);
 viewHolder.recordTv.setText(content);
 
 return convertView;
 }
 
 private class ViewHolder {
 TextView recordTv;
 }
}

3.RecordSQLiteOpenHelper

package com.example.administrator.searchapplication;
 
/**
 * Created by Administrator on 2018/2/11.
 */
 
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
 
/**
 * 搜尋記錄幫助類
 * Created by 05 on 2016/7/27.
 */
public class RecordSQLiteOpenHelper extends SQLiteOpenHelper {
 
 private final static String DB_NAME = "temp.db";
 private final static int DB_VERSION = 1;
 
 public RecordSQLiteOpenHelper(Context context) {
 super(context,DB_NAME,null,DB_VERSION);
 }
 
 @Override
 public void onCreate(SQLiteDatabase db) {
 String sqlStr = "CREATE TABLE IF NOT EXISTS records (_id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT);";
 db.execSQL(sqlStr);
 }
 
 @Override
 public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion) {
 
 }
}

4.RecordsDao

package com.example.administrator.searchapplication;
 
/**
 * Created by Administrator on 2018/2/11.
 */
 
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
 
import java.util.ArrayList;
import java.util.List;
 
/**
 * 搜尋記錄操作類
 * Created by 05 on 2016/7/27.
 */
public class RecordsDao {
 RecordSQLiteOpenHelper recordHelper;
 
 SQLiteDatabase recordsDb;
 
 public RecordsDao(Context context) {
 recordHelper = new RecordSQLiteOpenHelper(context);
 }
 
 //新增搜尋記錄
 public void addRecords(String record) {
 
 if (!isHasRecord(record)) {
  recordsDb = recordHelper.getReadableDatabase();
  ContentValues values = new ContentValues();
  values.put("name",record);
  //新增
  recordsDb.insert("records",values);
  //關閉
  recordsDb.close();
 }
 }
 
 //判斷是否含有該搜尋記錄
 public boolean isHasRecord(String record) {
 boolean isHasRecord = false;
 recordsDb = recordHelper.getReadableDatabase();
 Cursor cursor = recordsDb.query("records",null);
 while (cursor.moveToNext()) {
  if (record.equals(cursor.getString(cursor.getColumnIndexOrThrow("name")))) {
  isHasRecord = true;
  }
 }
 //關閉資料庫
 recordsDb.close();
 cursor.close();
 return isHasRecord;
 }
 
 //獲取全部搜尋記錄
 public List<String> getRecordsList() {
 List<String> recordsList = new ArrayList<>();
 recordsDb = recordHelper.getReadableDatabase();
 Cursor cursor = recordsDb.query("records",null);
 while (cursor.moveToNext()) {
  String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));
  recordsList.add(name);
 }
 //關閉資料庫
 recordsDb.close();
 cursor.close();
 return recordsList;
 }
 
 //模糊查詢
 public List<String> querySimlarRecord(String record){
 String queryStr = "select * from records where name like '%" + record + "%' order by name ";
 List<String> similarRecords = new ArrayList<>();
 Cursor cursor= recordHelper.getReadableDatabase().rawQuery(queryStr,null);
 
 while (cursor.moveToNext()) {
  String name = cursor.getString(cursor.getColumnIndexOrThrow("name"));
  similarRecords.add(name);
 }
 
 cursor.close();
 return similarRecords;
 }
 
 //清空搜尋記錄
 public void deleteAllRecords() {
 recordsDb = recordHelper.getWritableDatabase();
 recordsDb.execSQL("delete from records");
 
 recordsDb.close();
 }
 // 刪除
 public int delete(int _id) {
 
 SQLiteDatabase db = recordHelper.getWritableDatabase();
 int d = db.delete("records","_id=?",new String[] { _id + "" });
 
 db.close();
 return d;
 
 }
 
}

5.主函式佈局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">
 
 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="50dp">
 
 <LinearLayout
  android:layout_width="0dp"
  android:layout_height="match_parent"
  android:layout_weight="1">
 
  <ImageView
  android:layout_width="30dp"
  android:layout_height="match_parent"
  android:layout_gravity="center_vertical"
  android:padding="5dp"
  android:src="@mipmap/ic_launcher" />
 
  <EditText
  android:id="@+id/input_search_content_et"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:hint="請輸入你要搜尋的內容"
  android:imeOptions="actionSearch"
  android:singleLine="true"
  />
 
  <!-- 以上的singleLine和imeOptions屬性程式碼是將彈出的軟鍵盤的回車鍵替換成搜尋鍵的關鍵,當然也可以換成傳送鍵 等等,可以去查一下該屬性 -->
 
 </LinearLayout>
 
 <TextView
  android:id="@+id/search_content_cancel_tv"
  android:layout_width="wrap_content"
  android:layout_height="match_parent"
  android:layout_gravity="center_vertical"
  android:gravity="center"
  android:padding="10dp"
  android:text="取消"
  android:textSize="18sp" />
 
 </LinearLayout>
 <LinearLayout
 android:layout_width="match_parent"
 android:orientation="vertical"
 android:gravity="center|left"
 android:layout_height="30dp">
 <TextView
  android:id="@+id/tv_history"
  android:layout_width="wrap_content"
  android:layout_marginLeft="20dp"
  android:text="搜尋歷史"
  android:layout_height="wrap_content" />
 </LinearLayout>
 
 <RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 
 <LinearLayout
  android:id="@+id/search_content_show_ll"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical"></LinearLayout>
 
 </RelativeLayout>
 
</LinearLayout>

6.介面卡佈局

<?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:orientation="horizontal"
 android:layout_width="match_parent"
 android:layout_height="40dp">
 
 <TextView
  android:id="@+id/search_content_tv"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:drawableLeft="@mipmap/ic_launcher_round"
  android:drawablePadding="8dp"
  android:layout_margin="10dp"
  android:layout_gravity="center_vertical"
  />
 
 </LinearLayout>
 
</LinearLayout>

7.搜尋佈局

<?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:orientation="vertical"
 android:layout_width="match_parent"
 android:layout_height="wrap_content">
 
 <ListView
  android:id="@+id/search_records_lv"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"/>
 
 <View
  android:layout_width="match_parent"
  android:layout_height="0.1dp"
  android:background="@color/colorAccent"/>
 
 <TextView
  android:background="@color/colorPrimary"
  android:id="@+id/clear_all_records_tv"
  android:layout_width="match_parent"
  android:layout_height="40dp"
  android:textSize="16sp"
  android:gravity="center"
  android:text="清除歷史記錄"/>
 
 <View
  android:layout_width="match_parent"
  android:layout_height="0.1dp"
  android:background="@color/colorAccent"/>
 
 </LinearLayout>
 
</LinearLayout>

ok,demo資源裡有

二.仿bilibili搜尋框效果(三句程式碼實現)

Android本地實現搜尋歷史記錄

1.新增依賴:

apply plugin: 'com.android.application'
 
android {
 compileOptions {
 sourceCompatibility JavaVersion.VERSION_1_8
 targetCompatibility JavaVersion.VERSION_1_8
 }
 compileSdkVersion 29
 buildToolsVersion "29.0.2"
 defaultConfig {
 applicationId "com.example.mysgfceshicase"
 minSdkVersion 15
 targetSdkVersion 29
 versionCode 1
 versionName "1.0"
 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
 }
 buildTypes {
 release {
  minifyEnabled false
  proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro'
 }
 }
 packagingOptions {
 //解決編譯時com.android.builder.merge.DuplicateRelativeFileException: More than one file was found with OS independent path 'META-INF/rxjava.properties'這個錯誤
 exclude 'META-INF/rxjava.properties'
 }
}
 
dependencies {
 implementation fileTree(dir: 'libs',include: ['*.jar'])
 implementation 'androidx.appcompat:appcompat:1.0.2'
 implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
 testImplementation 'junit:junit:4.12'
 androidTestImplementation 'androidx.test.ext:junit:1.1.0'
 androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
 //noinspection GradleCompatible
 implementation 'com.android.support:recyclerview-v7:26.0.0-beta2'
 implementation 'com.android.support:cardview' +
  '-v7:26.0.0-beta2'
 testImplementation 'junit:junit:4.12'
 //仿轉轉輪播圖BAnner
 implementation 'com.tokiii:reveal-banner:1.0.1'
 //下拉重新整理、上拉載入、二級重新整理、淘寶二樓、RefreshLayout、OverScroll,Android智慧下拉重新整理框架,支援越界回彈、越界拖動,
 // 具有極強的擴充套件性,集成了幾十種炫酷的Header和 Footer
 implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0' //1.0.5及以前版本的老使用者升級需謹慎,API改動過大
 implementation 'com.scwang.smartrefresh:SmartRefreshHeader:1.1.0' //沒有使用特殊Header,可以不加這行
 //炫酷的輪播圖效果
 implementation 'com.github.ulez:dropindicator:0.0.2'
 //搜尋歷史記錄
 implementation 'com.wenwenwen888:searchbox:1.0.1'
 implementation 'com.jakewharton:butterknife:10.0.0'
 annotationProcessor 'com.jakewharton:butterknife-compiler:10.0.0'
 //noinspection GradleCompatible
 implementation 'com.android.support:design:28.0.0'
 implementation 'io.reactivex:rxandroid:1.1.0'
 implementation 'io.reactivex:rxjava:1.1.0'
// implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.1'
// implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.1'
// implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.1'
 implementation 'com.trello:rxlifecycle-components:0.6.1'
 implementation 'com.jakewharton.rxbinding:rxbinding:0.3.0'
 implementation 'com.jakewharton.rxbinding:rxbinding-appcompat-v7:0.3.0'
 implementation 'com.jakewharton.rxbinding:rxbinding-design:0.3.0'
 implementation 'com.github.bumptech.glide:glide:3.7.0'
 //gradle
 api ('com.alibaba.android:ultraviewpager:1.0.7.7@aar') {
 transitive = true
 }
 //首先引入gson庫
 compile 'com.google.code.gson:gson:2.8.1'
 
}
 //搜尋歷史記錄
 implementation 'com.wenwenwen888:searchbox:1.0.1'

2.主要實現:

//第一句,例項化: 
SearchFragment searchFragment = SearchFragment.newInstance();
 
//第二句,設定回撥:
searchFragment.setOnSearchClickListener(new IOnSearchClickListener() {
  @Override
  public void OnSearchClick(String keyword) {
  //這裡處理邏輯
  Toast.makeText(ToolBarActivity.this,keyword,Toast.LENGTH_SHORT).show();
  }
 });
//第三句,顯示搜尋框:
searchFragment.showFragment(getSupportFragmentManager(),SearchFragment.TAG);

3.全部程式碼:

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
 
import com.example.mysgfceshicase.R;
import com.wyt.searchbox.SearchFragment;
import com.wyt.searchbox.custom.IOnSearchClickListener;
 
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import butterknife.BindView;
import butterknife.ButterKnife;
 
public class SearchActivity extends AppCompatActivity implements Toolbar.OnMenuItemClickListener,IOnSearchClickListener {
 
 @BindView(R.id.toolbar)
 Toolbar toolbar;
 @BindView(R.id.search_info)
 TextView searchInfo;
 
 private SearchFragment searchFragment;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_search);
 ButterKnife.bind(this);
 
 toolbar.setTitle("SearchDialog");//標題
 setSupportActionBar(toolbar);
 
 searchFragment = SearchFragment.newInstance();
 
 toolbar.setOnMenuItemClickListener(this);
 
 searchFragment.setOnSearchClickListener(this);
 }
 
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
 //載入選單檔案
 getMenuInflater().inflate(R.menu.menu_main,menu);
 return true;
 }
 @Override
 public boolean onMenuItemClick(MenuItem item) {
 switch (item.getItemId()) {
  case R.id.action_search://點選搜尋
  searchFragment.showFragment(getSupportFragmentManager(),SearchFragment.TAG);
  break;
 }
 return true;
 }
 
 @Override
 public void OnSearchClick(String keyword) {
 searchInfo.setText(keyword);
 }
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="match_parent">
 
 <androidx.appcompat.widget.Toolbar
 android:id="@+id/toolbar"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:background="@color/colorPrimary"
 app:layout_scrollFlags="scroll|enterAlways" />
 
 <TextView
 android:id="@+id/search_info"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_below="@id/toolbar"
 android:gravity="center"
 android:text="Hello Android!"
 android:textSize="20sp" />
</RelativeLayout>

原始碼:搜尋歷史記錄

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。