最近在一个项目中使用到了搜索功能,特来此记录一下
本篇博文需要用到的知识点:
1.RecyclerView的简单操作
2.本地数据库的简单操作
3.ScrollView与RecyclerView的滑动冲突解决
废话不多说,先上效果图
文章图片
先看看工程界面截图
文章图片
其中HistorySearchAdapter是历史记录的适配器,HistorySearchUtil是本地数据库的管理工具类
1.
这个大概看看就好,可以根据自己的喜好设计
2.history_search_item.xml历史纪录RecyclerView的单项视图
3.数据库管理工具类HistorySearchUtil.java
public class HistorySearchUtil {/**
* 建表语句
*/
private static final String CREATE_HISTORY_SEARCH = "create table searchHistory (" +
"id integer primary key autoincrement, " +
"name text)";
private final String TAG = "HistorySearchUtil";
private final String TABLE_NAME = "searchHistory";
public Context mContext;
private static HistorySearchUtil mHistorySearchUtil;
private MyDatabaseHelper mMyDatabaseHelper;
private HistorySearchUtil(Context context) {
mMyDatabaseHelper = new MyDatabaseHelper(context, "Record.db", null, 1);
this.mContext = context;
}public static HistorySearchUtil getInstance(Context context) {//得到一个实例
if (mHistorySearchUtil == null) {
mHistorySearchUtil = new HistorySearchUtil(context);
} else if ((!mHistorySearchUtil.mContext.getClass()
.equals(context.getClass()))) {判断两个context是否相同
mHistorySearchUtil = new HistorySearchUtil(context);
}
return mHistorySearchUtil;
}/**
* 添加一条新纪录
* @param name
*/
public void putNewSearch(String name) {
SQLiteDatabase db = mMyDatabaseHelper.getWritableDatabase();
if (!isExist(name)) {//判断新纪录是否存在,不存在则添加
ContentValues values = new ContentValues();
values.put("name", name);
db.insert(TABLE_NAME, null, values);
}
}/**
* 判断记录是否存在
* @param name
* @return
*/
public boolean isExist(String name) {
SQLiteDatabase db = mMyDatabaseHelper.getWritableDatabase();
Cursor cursor = db.rawQuery("select * from " + TABLE_NAME + " where name = ?",
new String[]{name});
if (cursor.moveToFirst()) {//如果存在
return true;
} else {
return false;
}
}/**
* 查询所有历史纪录
* @return
*/
public List queryHistorySearchList() {
SQLiteDatabase db = mMyDatabaseHelper.getWritableDatabase();
List list = new ArrayList();
Cursor cursor = db.query(TABLE_NAME, null, null, null, null, null, null);
if (cursor.moveToFirst()) {
do {
String name = cursor.getString(cursor.getColumnIndex("name"));
list.add(name);
} while(cursor.moveToNext());
}
return list;
}/**
* 删除单条记录
* @param name
*/
public void deleteHistorySearch(String name) {
SQLiteDatabase db = mMyDatabaseHelper.getWritableDatabase();
if (isExist(name)) {
db.delete(TABLE_NAME, "name = " + "'" + name + "'", null);
}
}/**
* 删除所有记录
*/
public void deleteAllHistorySearch() {
SQLiteDatabase db = mMyDatabaseHelper.getWritableDatabase();
db.delete(TABLE_NAME, null, null);
}public class MyDatabaseHelper extends SQLiteOpenHelper {public MyDatabaseHelper(Context context, String name,
SQLiteDatabase.CursorFactory factoty, int version) {
super(context, name, factoty, version);
}@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_HISTORY_SEARCH);
//建表
}@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {}
}
}
其中操作比较简单,根据注释基本都能看懂
4.主界面操作MainActivity.java
package zzx.historysearch;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import adapter.HistorySearchAdapter;
import util.HistorySearchUtil;
public class MainActivity extends AppCompatActivity {private EditText searchEdit;
//搜索EditText
private TextView searchTv;
//搜索按钮,不过是以TextView形式
private RecyclerView histotyRecycler;
//历史纪录列表
private TextView historyEmptyTv;
//清空历史纪录按钮
private LinearLayout histotySearchLayout;
//历史记录整个布局private HistorySearchAdapter adapter;
//适配器private ArrayList histotyList = new ArrayList();
//历史纪录数组@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
android.support.v7.app.ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.hide();
}
initViews();
//初始化组件
initHistoryRecycler();
//初始化historyRecyclerView
getHistoryList();
//得到历史记录数组
setSearchTvListener();
//设置搜索按钮监听器
setHistoryEmptyTvListener();
//设置清空记录按钮监听器
}private void setHistoryEmptyTvListener() {
historyEmptyTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
HistorySearchUtil.getInstance(MainActivity.this)
.deleteAllHistorySearch();
getHistoryList();
adapter.notifyDataSetChanged();
//刷新列表
showViews();
}
});
}private void setSearchTvListener() {
searchTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
HistorySearchUtil.getInstance(MainActivity.this)
.putNewSearch(searchEdit.getText().toString());
//保存记录到数据库
getHistoryList();
adapter.notifyDataSetChanged();
showViews();
Toast.makeText(MainActivity.this, "此条记录已保存到数据库",
Toast.LENGTH_SHORT).show();
}
});
}/**
* 设置历史记录界面可见性,即记录为空时,不显示清空历史记录按钮等view
*/
private void showViews() {
if (histotyList.size() > 0) {
histotySearchLayout.setVisibility(View.VISIBLE);
} else {
histotySearchLayout.setVisibility(View.GONE);
}
}private void initHistoryRecycler() {
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
histotyRecycler.setLayoutManager(layoutManager);
histotyRecycler.setNestedScrollingEnabled(false);
//解决滑动冲突
adapter = new HistorySearchAdapter(this, histotyList);
histotyRecycler.setAdapter(adapter);
adapter.setOnItemClickListener(new HistorySearchAdapter.OnItemClickListener() {
@Override
public void onItemNameTvClick(View v, String name) {
searchEdit.setText(name);
}@Override
public void onItemDeleteImgClick(View v, String name) {
HistorySearchUtil.getInstance(MainActivity.this)
.deleteHistorySearch(name);
getHistoryList();
adapter.notifyDataSetChanged();
showViews();
}
});
}private void initViews() {
searchEdit = (EditText) findViewById(R.id.search_edit);
searchTv = (TextView) findViewById(R.id.search_tv);
historyEmptyTv = (TextView) findViewById(R.id.history_empty_tv);
histotyRecycler = (RecyclerView) findViewById(R.id.history_search_recycler);
histotySearchLayout = (LinearLayout) findViewById(R.id.history_search_layout);
}private void getHistoryList() {
histotyList.clear();
histotyList.addAll(HistorySearchUtil.getInstance(this)
.queryHistorySearchList());
adapter.notifyDataSetChanged();
showViews();
}
}
根据注释,应该都能看懂,值得注意的是。在本篇中解决ScrollView与RecyclerView的冲突的办法是,将ScrollView换成NestedScrollView,大家可以看看main_activity.xml里验证一下,然后在设置RecyclerView时将setNestedScrollingEnabled设置为false就可以了,即上文中的
histotyRecycler.setNestedScrollingEnabled(false);
至于NestedScrollView的其他用法,大家可以自行百度或者谷歌,这里就不展开了。
5.RecyclerView适配器HistorySearchAdapter.java
public class HistorySearchAdapter extends Adapter
implements View.OnClickListener {private Context mContext;
private OnItemClickListener mOnItemClickListener;
//item点击监听接口private List histotyList = new ArrayList();
public HistorySearchAdapter(Context context, List histotyList) {
this.mContext = context;
this.histotyList = histotyList;
}class ViewHolder extends RecyclerView.ViewHolder {private TextView nameTv;
private ImageView deleteImg;
private View itemView;
public ViewHolder(View itemView) {
super(itemView);
nameTv = (TextView) itemView.findViewById(R.id.search_history_item_tv);
deleteImg = (ImageView) itemView.findViewById(R.id.search_history_item_img);
this.itemView = itemView;
}
}@Override
public HistorySearchAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View view = LayoutInflater.from(mContext)
.inflate(R.layout.history_search_item, null);
ViewHolder holder = new ViewHolder(view);
return holder;
}@Override
public void onBindViewHolder(HistorySearchAdapter.ViewHolder holder, int position) {
holder.nameTv.setText(histotyList.get(position));
holder.nameTv.setTag(histotyList.get(position));
holder.deleteImg.setTag(histotyList.get(position));
holder.nameTv.setOnClickListener(this);
holder.deleteImg.setOnClickListener(this);
}public void onClick(View v) {
switch (v.getId()) {
case R.id.search_history_item_tv://点击历史纪录名称时调用
if (mOnItemClickListener != null) {
mOnItemClickListener.onItemNameTvClick(v, (String) v.getTag());
}
break;
case R.id.search_history_item_img://点击删除按钮时调用
if (mOnItemClickListener != null) {
mOnItemClickListener.onItemDeleteImgClick(v, (String) v.getTag());
}
break;
default:
}
}/**
* 设置item点击监听器
* @param listener
*/
public void setOnItemClickListener(OnItemClickListener listener) {
this.mOnItemClickListener = listener;
}@Override
public int getItemCount() {
return histotyList.size();
}/**
* item点击接口
*/
public interface OnItemClickListener {
void onItemNameTvClick(View v, String name);
//点击历史纪录名称时
void onItemDeleteImgClick(View v, String name);
//点击删除按钮时
}
}
在本适配器中采用了观察者模式,也是大众常用的一种模式,将删除按钮和历史纪录TextView的点击事件处理,交给了OnItemClickListener来处理,这样的话在MainActivity中可以很好的处理相关数据,也是代码更加规范吧。
好了,本篇博文到此也就结束了。至于item中使用的删除图片大家可以在阿里矢量库中寻找,里面非常多。
【android|android 利用数据库实现历史搜索记录功能】
推荐阅读
- Android|android属性之noHistory
- kotlin|kotlin顶部导航栏(TabLayout+viewpager)、底部导航栏(谷歌官方)
- android|Android历史版本
- android|android studio如何复制错误信息
- Android|TabLayout+ViewPager2的联合使用
- Android|薪资倒挂(行业内卷?2022年最新Android学习路线整理分享,带你干倒世界卷王)
- 实用网站|实用网站归纳
- 程序员|Android 这座山,我一定要爬到顶
- android|Android Studio开发毕业设计