Android EditText響應drawableRight等的點選事件
阿新 • • 發佈:2019-02-06
前言
我們在輸入框EditText中,經常會新增比如刪除X,下拉箭頭等圖示,以得到更好的使用者體驗和需求,如果放在右邊,我們經常設定drawableRight屬性來實現,那麼這些圖示如何響應點選事件呢?下面簡單記錄一下!
方法
首先我們要繼承AppCompatEditText,實現一個自定義的EditText(現在一般為了相容和實現MD風格,都會繼承AppCompatEditText,而不再去繼承EditText,另外AS也會給出相應的錯誤警告提示!)
然後藉助於onTouchEvent
,根據觸控位置來響應圖示的點選事件,判斷手指擡起的時候的x,y座標是否點選在drawable物件上。其中需要搞清楚這幾個引數:
event.getRawX()//相對於左邊界的絕對座標,以左上角為(0,0)
event.getX()//相對於自身的座標,以該空間的左上角為(0,0)
getLeft()//相當於margin,控制元件左邊界相對於父控制元件的距離
getPaddingLeft()//相當於padding,控制元件中元素相對於控制元件的間距
getBounds().width()//獲取元素繪製區域的寬度
drawableRight.getIntrinsicWidth()//獲取drawable的實際寬度
那麼就需要得到這個圖示,這裡通過呼叫getCompoundDrawables()
可以獲取一個長度為4的drawable陣列,存放drawableLeft,Right,Top,Bottom四個圖片資源物件:
final int DRAWABLE_LEFT = 0;
final int DRAWABLE_TOP = 1;
final int DRAWABLE_RIGHT = 2;
final int DRAWABLE_BOTTOM = 3;
可以根據圖示的位置,拿到對應的圖片Drawable。
最後,通過宣告一個介面,定義一個回撥方法,這裡就不細說了,比較常見了!
具體實現
public class DropDownEditText extends AppCompatEditText {
final int DRAWABLE_LEFT = 0;
final int DRAWABLE_TOP = 1;
final int DRAWABLE_RIGHT = 2;
final int DRAWABLE_BOTTOM = 3;
public DropDownEditText(Context context) {
super(context);
}
public DropDownEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public interface OnDropArrowClickListener {
void onDropArrowClick();
}
private OnDropArrowClickListener onDropArrowClickListener;
public void setOnDropArrowClickListener(OnDropArrowClickListener onDropArrowClickListener) {
this.onDropArrowClickListener = onDropArrowClickListener;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
Drawable drawableRight = getCompoundDrawables()[DRAWABLE_RIGHT];
if (drawableRight != null) {
//本次點選事件的x軸座標,如果>當前控制元件寬度-控制元件右間距-drawable實際展示大小
if (event.getX() >= (getWidth() - getPaddingRight() - drawableRight.getIntrinsicWidth())) {
//設定點選EditText右側圖示EditText失去焦點,
// 防止點選EditText右側圖示EditText獲得焦點,軟鍵盤彈出
setFocusableInTouchMode(false);
setFocusable(false);
if (onDropArrowClickListener != null) {
onDropArrowClickListener.onDropArrowClick();
}
} else {
setFocusableInTouchMode(true);
setFocusable(true);
}
}
}
return super.onTouchEvent(event);
}
}
示例中展示了圖示在右邊的情況,同樣的其他的位置:
右邊:
//另外一種直接的方法
//其實就是算該drawable最左邊的x座標,drawableRight.getIntrinsicWidth()==drawableRight.getBounds().width()等於圖示的寬度
event.getRawX() >= (getRight() - drawableRight.getBounds().width())
左邊:
/**getX是相對於控制元件本身的左上角的x座標,<= 控制元件左邊距+圖片物件實際的寬度.這邊的getLeft相當於margin,getPaddingLeft相當於padding*/
event.getX() <= getLeft() + drawableLeft.getIntrinsicWidth()
event.getRawX() <= (getLeft() + drawableLeft.getBounds().width())
上邊:
event.getY() <= getTop() + drawableTop.getIntrinsicHeight()
下邊:
event.getX() > getHeight() - drawableBottom.getIntrinsicWidth()
呼叫
直接得到例項,呼叫方法即可:
editText = (DropDownEditText) findViewById(R.id.xxxxx);
editText.setOnDropArrowClickListener(new DropDownEditText.OnDropArrowClickListener() {
@Override
public void onDropArrowClick() {
//xxxxxxxx
}
});
問題
setFocusableInTouchMode(false);
setFocusable(false);
這種方法,雖然可以避免彈出輸入法,但是EditText下邊的線,還是會亮一下,感覺體驗不太好,如果有知道的,可以指導一下,謝謝!