在android的應用開發中,我認爲添加drawable類型的圖片非常好用。爲TextView或者EditText添加一個drawableLeft圖片或者drawableRight圖片非常方便,在一些情況下,還能減少佈局層數,優化程序性能。比如我們想實現以下效果
我們只要給TextView添加drawableLeft圖片就好,不要在TextView的外層在嵌套一層佈局了
但是,有時候我們想給這些drawable的圖片添加一個監聽器,方便我們實現一些業務代碼或者跳轉邏輯
根據以往我們的開發經驗,要給一個控件註冊監聽器,必須拿到他的實例對象,把監聽器註冊給這個對象,才能完成回調
但是在現在這種情況下,TextView和左邊那張圖片明顯是一個控件,我們無法在對象層面把它們區分開來
這時候,我們只能在android層面上解決這個問題。
在我之前分享的博客中 Android 事件分發機制詳解--真正的解析中已經提到,每個view的事件分發首先會調用dispatchTouchEvent,在這個方法中會調用onTouch事件,根據onTouch的返回值決定是否往下傳遞,也就是說onClick事件的執行是在onTouch之後,並且是否執行是受到onTouch返回值控制的。那麼對我們來說, 只要在onTouch事件中對點擊圖片還是點擊TextView做出區分,那麼就能解決這個問題了。那怎麼做出區分呢?其實也很簡單,通過x軸上的座標就能做出區分,可以判斷點擊區域,從而確定把事件交給哪個部分。
那麼接下來我們一起看下實現代碼,清楚原理之後,其實代碼邏輯非常簡單。
//drawable是拿一個數組來保存上下左右4個drawable對象的 分別對應0,1,2,3
private static final int DRAWABLE_RIGHT = 2;
//首先獲得我們TextView的實例對象
TextView mDemoTv =(TextView) findViewById(R.id.xxx);
mDemoTv .setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mDemoTv .getCompoundDrawables()[DRAWABLE_RIGHT == null){
return false;
}
//這裏一定要對點擊事件類型做一次判斷,否則你的點擊事件會被執行2次
if (event.getAction() != MotionEvent.ACTION_UP){
return false;
} if (event.getX() > mDemoRv.getWidth() -mDemoTv.getCompoundDrawables()[DRAWABLE_RIGHT.getBounds.width()) {
//do something you want
return true;
}
}
});
計算公式就是 整個控件寬度-圖片寬度 如果x大於這個值就代表進入了drawableRight的區域了 同理,drawableLeft也可以用這種方式計算。並且由於onTouch返回了一個true,不會對TextView的onClick事件進行干擾
最後在普及下getX()和getRawX()的區別
getX是獲取以當前控件左上角爲座標原點計算的X軸座標直.獲得的是一個相對的座標
getRawX 獲取的是以屏幕左上角爲座標原點計算的X軸座標直.獲得的是一個真實的座標
所以我們這裏選取的是getX()的方法