当查询已经成标配
查询是已成为每个应用常用的功能,也正是这样前端后对查询的设计需求也日益增加,本文针对前端(Android端)查询控件做一个例子;
控件设计与逻辑
产品的设计UI图;
要达到如下
1|、默认第一张图,中间展示默认提示文字,左边搜索图标;
2、输入文字后提示语消失,搜索的文字在后面,另外右边显示取消的图标
3、外加一个性能需求,我们搜索没必要每输入一个字都请求一次后台数据,有时候用户很快输入很多字符,就会导致大量没用的期过后,可以输入完等一段时间没输入才发起查询请求;
具体代码实现
先贴出代码后面做关键的解释
1 public class SearchDisplayView extends EditText { 2 private static int COUNTDOWN_INTERVAL = 300; 3 private DelayAfterTextChangedListener mDelayTextChangedListener; 4 5 public static interface DelayAfterTextChangedListener { 6 public void afterTextChanged(String keyword); 7 } 8 9 private CountDownTimer mCountDownTimer = new CountDownTimer(COUNTDOWN_INTERVAL, COUNTDOWN_INTERVAL) { 10 11 @Override 12 public void onTick(long millisUntilFinished) { 13 //间隔执行 14 } 15 16 @Override 17 public void onFinish() { 18 if(mDelayTextChangedListener != null) { 19 mDelayTextChangedListener.afterTextChanged(getText().toString()); 20 } 21 } 22 }; 23 24 public SearchDisplayView(Context context) { 25 this(context, null); 26 } 27 28 public SearchDisplayView(Context context, AttributeSet attrs) { 29 super(context, attrs); 30 if (isInEditMode()) { 31 return; 32 } 33 initViews(); 34 } 35 36 private void initViews() { 37 setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_search, 0, 0, 0); 38 setTextAppearance(getContext(), R.style.LHBTextView_Medium_DaryGray); 39 setHintTextColor(getResources().getColor(R.color.light_gray)); 40 setBackgroundResource(R.drawable.bg_corner_white); 41 int paddingLeft = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, 42 getResources().getDisplayMetrics()); 43 int paddingTop = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, 44 getResources().getDisplayMetrics()); 45 setPadding(paddingLeft, paddingTop, paddingLeft, paddingTop); 46 setCompoundDrawablePadding(paddingLeft); 47 setGravity(Gravity.CENTER); 48 49 setOnTouchListener(new OnTouchListener() { 50 @Override 51 public boolean onTouch(View v, MotionEvent event) { 52 if (event.getAction() == MotionEvent.ACTION_UP) { 53 if (getCompoundDrawables()[2] != null) { 54 boolean touchable = event.getX() > (getWidth() - getTotalPaddingRight()) && 55 (event.getX() < ((getWidth() - getPaddingRight()))); 56 if (touchable) { 57 setText(""); 58 } 59 } 60 } 61 return false; 62 } 63 }); 64 65 addTextChangedListener(new TextWatcher() { 66 @Override 67 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 68 69 } 70 71 @Override 72 public void onTextChanged(CharSequence s, int start, int before, int count) { 73 boolean empty = TextUtils.isEmpty(s); 74 setCompoundDrawablesWithIntrinsicBounds(0, 0, !empty ? R.drawable.ic_dialog_close : 0, 0); 75 } 76 77 @Override 78 public void afterTextChanged(Editable s) { 79 if(mDelayTextChangedListener != null) { 80 mCountDownTimer.cancel(); 81 mCountDownTimer.start(); 82 } 83 } 84 }); 85 86 setOnFocusChangeListener(new View.OnFocusChangeListener() { 87 @Override 88 public void onFocusChange(View v, boolean hasFocus) { 89 if (hasFocus) { 90 setTag(getHint()); 91 setHint(""); 92 } else { 93 setHint(getTag().toString()); 94 } 95 setGravity(hasFocus ? Gravity.LEFT : Gravity.CENTER); 96 setCompoundDrawablesWithIntrinsicBounds(!hasFocus ? R.drawable.ic_search : 0, 0, getCompoundDrawables()[2] != null ? R.drawable.ic_dialog_close : 0, 0); 97 } 98 }); 99 } 100 101 public void setDelayAfterTextChangedListener(DelayAfterTextChangedListener afterTextChangedListener) { 102 mDelayTextChangedListener = afterTextChangedListener; 103 } 104 105 @Override 106 protected void onDetachedFromWindow() { 107 super.onDetachedFromWindow(); 108 if (mCountDownTimer != null) { 109 mCountDownTimer.cancel(); 110 } 111 } 112 113 public void setDisplayHint(int resid) { 114 setHint(resid); 115 setTag(getResources().getString(resid)); 116 } 117 }
1、代码继承EditText实现输入框的查询;
2、initView()初始化查询控件的样式和相关事件触发;
3、setOnTouchListener()处理右边"点击关闭图标"的出现时机和清楚输入文字处理;
4、addTextChangedListener() 监听文字变化,当中 onTextChanged() 回调函数处理左边样式控制,afterTextChanged() 做延时查询处理;
5、setOnFocusChangeListener() 处理在获得焦点的时候样式的变化,如提示语消失和文字靠左;
6、延时处理核心在CountDownTimer这个匿名内部类段落,里面重写了CountDownTimer回调方法并实现自己的逻辑,这是一个时间倒数的处理类,通过人肉实验300毫秒能处理好少请求并查询速度响应的时点;到最后在控件脱离窗体的时候onDetachedFromWindow(),为了安全起见别忘了重新取消下定时的操作;
7、这样控件并封装完成,在需要使用的地方直接引用就可以,需要延时的则调用监听方法setDelayAfterTextChangedListener() 可以使用;
最后
上面以安卓为例子,IOS WEB端当然也可以实现自己的延时查询控件,达到一次编写,到处运行;