利用SimpleCursorAdapter自定义SearchView实践
导语
搜索栏是咱们生活中随处可见的一个小零件,可是离了他们在解决问题时的时间复杂度就如同从nlogn上升到了np问题,下面这个就是我们最常见的一种搜索栏。
那么接下来就让我们尽可能的实现相似的效果。
数据库
首先让我们写一个SqliteOpenHelper用于操纵数据库
package edu.fjnu.mysearchview;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBSqliteOpenHelper extends SQLiteOpenHelper {
private static String name="data.db";
private static Integer version= 1;
public DBSqliteOpenHelper(Context context){
super(context,name,null,version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("Create table records(id integer primary key autoincrement,name varchar(256),photo_id integer)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
文字搜索栏
package edu.fjnu.mysearchview;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.appcompat.widget.AppCompatEditText;
public class ModEditText extends AppCompatEditText {
private Drawable clearDrawable;
private Drawable searchDrawable;
public ModEditText(Context context) {
super(context);
init();
}
public ModEditText(Context context, AttributeSet attrsr){
super(context,attrsr);
init();
}
public ModEditText(Context context,AttributeSet attrsr,int defStyleAttr){
super(context,attrsr,defStyleAttr);
init();
}
private void init() {
clearDrawable = getResources().getDrawable(R.drawable.delete);
searchDrawable = getResources().getDrawable(R.drawable.search);
setCompoundDrawablesWithIntrinsicBounds(searchDrawable,null,null,null);
}
//要实现输入文字时能显示一键删除图标,需要重写onTextChanged()方法与onFocusChanged()
@Override
protected void onTextChanged(CharSequence text,int start,int lengthBefore,int lengthAfter){
super.onTextChanged(text,start,lengthBefore,lengthAfter);
setClearIconVisible(hasFocus()&&text.length()>0);//当触点选中搜索框为焦点,同时EditText中文字大于0时将删除按钮设为可见
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
setClearIconVisible(focused && length()>0);//当选中为焦点时设为可见
}
//判断是否显示删除图标
private void setClearIconVisible(boolean visible) {
setCompoundDrawablesWithIntrinsicBounds(searchDrawable,null,
visible?clearDrawable:null,null);
}
//设置Touch事件
public boolean onTouchEvent(MotionEvent event){
switch (event.getAction()){
case MotionEvent.ACTION_UP://当触点松开时
Drawable drawable =clearDrawable;
if(drawable !=null && event.getX()<=(getWidth()-getPaddingRight())
&&event.getX()>=(getWidth()-getPaddingRight()-drawable.getBounds().width())){
setText("");
}
//if判断条件:触点抬起时位置坐标<=(控件的宽度-控件的右侧边缘距离[即删除图标的右侧坐标])
//同时触点抬起时位置坐标<=删除图标的左侧图标
//即触点抬起时位置坐标在删除图标时清空Text栏
break;
}
return super.onTouchEvent(event);
}
}
自定义ListView
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
由于我们需要让ListView与ScrollView结合,使列表能够滚动,为此我们需要重写ListView的onMeasure()方法
通过MeasureSpec.makeMeasureSpec(int size,int mode)方法将listview设置为无边界,同时根据布局的大小与内容的多少灵活确定Listview的高度
xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:focusableInTouchMode="true"
android:orientation="vertical">
<LinearLayout
android:id="@+id/search_block"
android:layout_width="match_parent"
android:layout_height