本文主要为大家分享了Android实现搜索功能,并且可以实时显示搜索的历史记录,根据输入的内容去模糊查询,供大家参考,界面图如下。
本案例实现起来也非常的简单,所以可以直接拿来嵌入项目中使用,主要涉及到的知识点:
1、数据库的增删改查操作
2、监听软键盘回车按钮设置为搜索按钮
3、使用TextWatcher( )进行实时筛选
4、已搜索的关键字再次搜索不会重复添加到数据库
既然是要保存搜索记录,首先得建立数据库表:
[java] view plain copy
- /**
- * 搜索记录帮助类
- * 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) {
- }
- }
数据库操作类 ,增删改查都在里面:
[html] view plain copy
- /**
- * 搜索记录操作类
- * 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", null, values);
- //关闭
- recordsDb.close();
- }
- }
- //判断是否含有该搜索记录
- public boolean isHasRecord(String record) {
- boolean isHasRecord = false;
- recordsDb = recordHelper.getReadableDatabase();
- Cursor cursor = recordsDb.query("records", null, null, null, null, null, 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, null, null, null, null, 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();
- }
- }
数据库类已经封装好了,接下来就是界面代码:
[html] view plain copy
- <span style="color:#333333;"><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:background="@color/base_green"
- android:layout_width="match_parent"
- android:layout_height="50dp">
- <LinearLayout
- android:layout_margin="10dp"
- android:background="@drawable/input_border_layout"
- android:layout_weight="1"
- android:layout_width="0dp"
- android:layout_height="match_parent">
- <ImageView
- android:padding="5dp"
- android:layout_gravity="center_vertical"
- android:layout_width="30dp"
- android:layout_height="match_parent"
- android:src="@mipmap/my_village_search"/>
- <EditText
- android:id="@+id/input_search_content_et"
- android:layout_margin="5dp"
- android:textSize="14sp"
- android:singleLine="true"
- android:imeOptions="actionSearch"
- android:layout_gravity="center_vertical"
- android:background="@drawable/input_no_border_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:hint="请输入你要搜索的内容"/></span>
- <!-- 以上的singleLine和imeOptions属性代码是将弹出的软键盘的回车键替换成搜索键的关键,当然也可以换成发送键 等等,可以去查一下该属性 --></span>
- </LinearLayout>
- <TextView
- android:id="@+id/search_content_cancel_tv"
- android:padding="10dp"
- android:layout_gravity="center_vertical"
- android:gravity="center"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:textSize="18sp"
- android:text="取消"
- android:textColor="@color/white"/>
- </LinearLayout>
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <LinearLayout
- android:orientation="vertical"
- android:id="@+id/search_content_show_ll"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- </LinearLayout>
- </RelativeLayout>
- </LinearLayout></span>
因为是将搜索的历史信息做成显示隐藏的效果,所以单独写了一个历史信息的layout:
[html] view plain copy
- <?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/custom_gray"/>
- <TextView
- android:background="@color/white"
- android:id="@+id/clear_all_records_tv"
- android:layout_width="match_parent"
- android:layout_height="40dp"
- android:textSize="16sp"
- android:gravity="center"
- android:textColor="@color/clear_red"
- android:text="清除历史记录"/>
- <View
- android:layout_width="match_parent"
- android:layout_height="0.1dp"
- android:background="@color/custom_gray"/>
- </LinearLayout>
- </LinearLayout>
既然用到了listview来显示历史搜索信息,就需要写listview的item:
[html] view plain copy
- <?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:background="@color/white"
- 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/search_icon"
- android:drawablePadding="8dp"
- android:layout_margin="10dp"
- android:layout_gravity="center_vertical"
- />
- </LinearLayout>
- </LinearLayout>
用到了listview,当然还需要适配器,因为目前只有文本可以使用SimpleAdapter,为了以后能添加别的,我还是自定义了一个Adapter:
[java] view plain copy
- /**
- * 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() {
- return searchRecordsList.size() == 0 ? 0 : 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.saerch_records_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;
- }
- }
最后就是界面代码了:
[java] view plain copy
- /**
- * 搜索界面
- * Created by 05 on 2016/7/26.
- */
- public class SearchContentActivity extends BaseActivity 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;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- BaseSetContentView(R.layout.activity_search_content);
- 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);
- //添加搜索view
- searchRecordsLl.addView(recordsHistoryView);
- }
- //初始化搜索历史记录View
- private void initRecordsView() {
- recordsHistoryView = LayoutInflater.from(this).inflate(R.layout.search_records_list_layout, 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();
- //根据关键词去搜索
- } else {
- ToastUtils.showToast(SearchContentActivity.this, "搜索内容不能为空");
- }
- }
- 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 start, int before, int count) {
- }
- @Override
- public void afterTextChanged(Editable s) {
- 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) {
- //将获取到的字符串传到搜索结果界面
- }
- });
- }
- //当没有匹配的搜索数据的时候不显示历史记录栏
- 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);
- break;
- }
- }
- //颠倒list顺序,用户输入的信息会从上依次往下显示
- private void reversedList(){
- searchRecordsList.clear();
- for(int i = tempList.size() - 1 ; i >= 0 ; i --){
- searchRecordsList.add(tempList.get(i));
- }
- }
- }
以上就是实现搜索记录存储,搜索信息模糊查询的全部代码了,供大家参考,当然也给自己提供一个整理思路的锻炼。