最近在做edit搜索,在输入的时候频繁调用接口,消耗太大,并且感觉用户体验也不好,就趁着空余时间想着优化下 搜索edittext,准备自定义 个edittext,预想的效果是,用户在输入完成后,有个延迟调用接口的时间,给用户一个反应时间,避免了接口的频繁调用,好了,有了想法就开始干,其实原理也很简单 利用handler 延迟发送 数据就行了。最后又新增了个 删除按钮的 功能。嘻嘻! 下面是代码。喜欢的点个赞谢谢!想支持我的 就在这个链接里下载吧https://download.csdn.net/download/yy292916/16634266
/**
* Created by Yy (Attractive Alpaca) on 2021/4/7.
* 优化搜索结果专用 的editText
* 自带一键删除按钮
*/
public class SearchEditText extends androidx.appcompat.widget.AppCompatEditText implements Handler.Callback, TextWatcher, View.OnFocusChangeListener {
private final MyHandler mHandler = new MyHandler(this);
//删除按钮的引用
private Drawable mClearDrawable;
//控件是否有焦点
private boolean hasFocus;
//延时时间
private static final int DELAYED_TIME = 1000;
//收到数据的回调
private OnSearchListener onSearchListener;
public void setOnSearchListener(OnSearchListener onSearchListener) {
this.onSearchListener = onSearchListener;
}
public SearchEditText(@NonNull Context context) {
super(context);
initView();
}
public SearchEditText(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView();
}
public SearchEditText(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
@SuppressLint("UseCompatLoadingForDrawables")
private void initView() {
//获取EditText的DrawableRight,假如没有设置我们就使用默认的图片
mClearDrawable = getCompoundDrawables()[2];
if (mClearDrawable == null) {
mClearDrawable = getResources().getDrawable(R.mipmap.icon_logo_close);
}
mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());
//默认设置隐藏图标
setClearIconVisible(false);
//设置焦点改变的监听
setOnFocusChangeListener(this);
addTextChangedListener(this);
}
@Override
public boolean handleMessage(@NonNull Message message) {
//输入1s后显示(1s内输入数据无变化)
if (message.what == 999 && onSearchListener != null) {
onSearchListener.searchResult((String) message.obj);
}
if (message.what == 998 && onSearchListener != null) {
onSearchListener.clearSearch();
}
return false;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (hasFocus) {
setClearIconVisible(s.length() > 0);
}
}
@Override
public void afterTextChanged(Editable s) {
if (mHandler.hasMessages(999)) {
mHandler.removeMessages(999);
}
if (mHandler.hasMessages(998)) {
mHandler.removeMessages(998);
}
if (s.toString().trim().length() == 0) {
mHandler.sendEmptyMessageDelayed(998, DELAYED_TIME);
} else {
Message msg = Message.obtain();
msg.what = 999;
msg.obj = s.toString().trim();
mHandler.sendMessageDelayed(msg, DELAYED_TIME);
}
}
/**
* 因为我们不能直接给EditText设置点击事件,所以我们用记住我们按下的位置来模拟点击事件
* 当我们按下的位置 在 EditText的宽度 - 图标到控件右边的间距 - 图标的宽度 和
* EditText的宽度 - 图标到控件右边的间距之间我们就算点击了图标,竖直方向就没有考虑
*/
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (getCompoundDrawables()[2] != null) {
boolean touchable = event.getX() > (getWidth() - getTotalPaddingRight())
&& (event.getX() < ((getWidth() - getPaddingRight())));
if (touchable) {
this.setText("");
}
}
}
return super.onTouchEvent(event);
}
/**
* 当焦点发生变化的时候,判断里面字符串长度设置清除图标的显示与隐藏
*/
@Override
public void onFocusChange(View v, boolean hasFocus) {
this.hasFocus = hasFocus;
if (hasFocus) {
setClearIconVisible(getText().length() > 0);
} else {
setClearIconVisible(false);
}
}
/**
* 设置清除图标的显示与隐藏,调用setCompoundDrawables为EditText绘制上去
*/
protected void setClearIconVisible(boolean visible) {
Drawable right = visible ? mClearDrawable : null;
setCompoundDrawables(getCompoundDrawables()[0],
getCompoundDrawables()[1], right, getCompoundDrawables()[3]);
}
public interface OnSearchListener {
void searchResult(String str);
void clearSearch();
}
private static class MyHandler extends Handler {
WeakReference<SearchEditText> mActivityReference;
MyHandler(SearchEditText editText) {
mActivityReference = new WeakReference<>(editText);
}
@Override
public void handleMessage(@NotNull Message msg) {
SearchEditText editText = mActivityReference.get();
if (editText != null) {
editText.handleMessage(msg);
}
}
}