自定義view事件分發機制的細枝末節
當view確定自身已經不再適合現有的區域時,該view本身調用這個方法要求parent view(父類的視圖)重新調用他的onMeasure onLayout來重新設置自己位置。特別是當view的layoutparameter發生改變,并且它的值還沒能應用到view上時,這時候適合調用這個方法。
postInvalidate 與 invalidate
界面刷新 onDraw方法會執行,區別就是Invalidate不能直接在線程中調用,因為他是違背了單線程模型:Android UI操作并不是線程安全的,并且這些操作必須在UI線程中調用。 鑒于此,如果要使用invalidate的刷新,那我們就得配合handler的使用,使異步非ui線程轉到ui線程中調用,如果要在非ui線程中直接使用就調用postInvalidate方法即可,這樣就省去使用handler的煩惱。
view提供的方法
getTop:獲取到的,是view自身的頂邊到其父布局頂邊的距離 getLeft:獲取到的,是view自身的左邊到其父布局左邊的距離 getRight:獲取到的,是view自身的右邊到其父布局左邊的距離 getBottom:獲取到的,是view自身的底邊到其父布局頂邊的距離
MotionEvent提供的方法
getX():獲取點擊事件相對控件左邊的x軸坐標,即點擊事件距離控件左邊的距離 getY():獲取點擊事件相對控件頂邊的y軸坐標,即點擊事件距離控件頂邊的距離 getRawX():獲取點擊事件相對整個屏幕左邊的x軸坐標,即點擊事件距離整個屏幕左邊的距離 getRawY():獲取點擊事件相對整個屏幕頂邊的y軸坐標,即點擊事件距離整個屏幕頂邊的距離
當以下代碼時:
view中點擊事件代碼:
public boolean onTouchEvent(MotionEvent event) {
int touchEvent = event.getAction();
switch (touchEvent) {
case MotionEvent.ACTION_DOWN:
System.out.println("CustomView getXdown="+event.getX()+" getYdown="+event.getY());
System.out.println("CustomView getRawXdown="+event.getRawX()+" getRawYdown="+event.getRawY());
System.out.println("CustomView eventdown="+super.onTouchEvent(event));
break;
case MotionEvent.ACTION_UP:
System.out.println("CustomView getXup="+event.getX()+" getYup="+event.getY());
System.out.println("CustomView getRawXup="+event.getRawX()+" getRawYup="+event.getRawY());
System.out.println("CustomView eventup="+super.onTouchEvent(event));
break;
case MotionEvent.ACTION_MOVE:
break;
default:
break;
}
return true;
}
activity中點擊事件代碼
@Override
public boolean onTouchEvent(MotionEvent event) {
int touchEvent = event.getAction();
switch (touchEvent) {
case MotionEvent.ACTION_DOWN:
System.out.println("MainActivity getXdown="+event.getX()+" getYdown="+event.getY());
System.out.println("MainActivity getRawXdown="+event.getRawX()+" getRawYdown="+event.getRawY());
System.out.println("MainActivity eventdown="+super.onTouchEvent(event));
break;
case MotionEvent.ACTION_UP:
System.out.println("MainActivity getXup="+event.getX()+" getYup="+event.getY());
System.out.println("MainActivity getRawXup="+event.getRawX()+" getRawYup="+event.getRawY());
System.out.println("MainActivity eventup="+super.onTouchEvent(event));
break;
case MotionEvent.ACTION_MOVE:
break;
default:
break;
}
return super.onTouchEvent(event);
}
得到輸出結果:
因為view中返回true,消費掉了點擊事件,所以activity中不打印。
而當把view中點擊事件代碼修改成以下情況:
view代碼:
public boolean onTouchEvent(MotionEvent event) {
int touchEvent = event.getAction();
switch (touchEvent) {
case MotionEvent.ACTION_DOWN:
System.out.println("CustomView getXdown="+event.getX()+" getYdown="+event.getY());
System.out.println("CustomView getRawXdown="+event.getRawX()+" getRawYdown="+event.getRawY());
System.out.println("CustomView eventdown="+super.onTouchEvent(event));
break;
case MotionEvent.ACTION_UP:
System.out.println("CustomView getXup="+event.getX()+" getYup="+event.getY());
System.out.println("CustomView getRawXup="+event.getRawX()+" getRawYup="+event.getRawY());
System.out.println("CustomView eventup="+super.onTouchEvent(event));
break;
case MotionEvent.ACTION_MOVE:
break;
default:
break;
}
return super.onTouchEvent(event);
}
則返回如下
因為view中返回false,所以點擊沒有被消費掉,只有down不執行up,因此執行至activity,而activity也是返回false,本來activity也不會執行up,但是沒有更上級,所以這邊只有在activity中吧up事件給執行了。(這句話如有錯誤請盡量提出)
來自:http://www.jianshu.com/p/517368680bc1