android layout 点击,Tips_Android点击事件(Down、Move、Up)的分发_重写Layout响应拖动事件...
首先是點擊事件在不同的布局層次中傳遞的。
理解Down事件再哪個層次被消費(攔截),后續的Move、Up的點擊事件如何傳遞。
其中ViewGroup中onInterceptTouchEvent方法用來對事件作預處理的,對于Down事件返回true表示要消費這個事件,不再向子View傳遞。
onInterceptTouchEvent用于改變事件的傳遞方向。決定傳遞方向的是返回值,返回為false時事件會傳遞給子控件,返回值為true時事件會傳遞給當前控件的onTouchEvent(),這就是所謂的Intercept(攔截)。
[tisa ps:正確的使用方法是,在此方法內僅判斷事件是否需要攔截,然后返回。即便需要攔截也應該直接返回true,然后由onTouchEvent方法進行處理。]
onTouchEvent用于處理事件,返回值決定當前控件是否消費(consume)了這個事件。尤其對于ACTION_DOWN事件,返回true,表示我想要處理后續事件;返回false,表示不關心此事件,并返回由父類進行處理。
可能你要問是否消費了又區別嗎,反正我已經針對事件編寫了處理代碼?答案是有區別!比如ACTION_MOVE或者ACTION_UP發生的前提是一定曾經發生了ACTION_DOWN,如果你沒有消費ACTION_DOWN,那么系統會認為ACTION_DOWN沒有發生過,所以ACTION_MOVE或者ACTION_UP就不能被捕獲。
在沒有重寫onInterceptTouchEvent()和onTouchEvent()的情況下(他們的返回值都是false),?對上面這個布局,MotionEvent事件的傳遞順序如下:
當某個控件的onInterceptTouchEvent()返回值為true時,就會發生截斷,事件被傳到當前控件的onTouchEvent()。如我們將LayoutView2的onInterceptTouchEvent()返回值為true,則傳遞流程變成:
如果我們同時將LayoutView2的onInterceptTouchEvent()和onTouchEvent()設置成true,那么LayoutView2將消費被傳遞的事件,同時后續事件(如跟著ACTION_DOWN的ACTION_MOVE或者ACTION_UP)會直接傳給LayoutView2的onTouchEvent(),不傳給其他任何控件的任何函數。同時傳遞給子空間一個ACTION_CANCEL事件。傳遞流程變成(圖中沒有畫出ACTION_CANCEL事件):
?? ? ? ??
[tisa ps:總體來看,?onInterceptTouchEvent是自rootview向下傳遞, onTouchEvent正好相反。]
基于以上點擊事件的傳遞,可以重寫一些ViewGroup,響應其拖動的事件,比如LinearLayout,重寫其onInterceptTouchEvent()和onTouchEvent()兩個方法可以達到效果(具體看實際布局中子view對事件的消費情況而定)
//true是攔截,false是不攔截。這里只是預處理判斷點擊的位置,不攔截。
@Override
public?boolean?onInterceptTouchEvent(MotionEvent?ev)?{
if?(ev.getAction()?==?MotionEvent.ACTION_DOWN)?{
int?x?=?(int)?ev.getX();
int?y?=?(int)?ev.getY();
dragSrcPointY?=?y;
FTLog.d(_TAG,?"x="?+?x?+?",y="?+?y);
}
return?super.onInterceptTouchEvent(ev);
}
@Override
public?boolean?onTouchEvent(MotionEvent?ev)?{
//只有判斷是點擊觸發拖動的區域時,才進行處理。否則不處理,交予FTBounceListView舊邏輯處理。
int?action?=?ev.getAction();
switch?(action)?{
case?MotionEvent.ACTION_DOWN:
//FTLog.e("TMS===down==",?"tms");
//bConsumeDown?=?true;
return?true;
//case?MotionEvent.ACTION_MOVE:
//FTLog.e("TMS===move==",?"tms");
//if?(bConsumeDown?==?false)
//{
//super.onTouchEvent(ev);
//}
//break;
case?MotionEvent.ACTION_UP:
FTLog.d(_TAG,?"x="+ev.getX()+",y="+ev.getY());
if?(ev.getY()?
{//向上拖動距離超過20dip,才finish,動畫效果。
try?{
((Activity)?context).finish();
((Activity)?context).overridePendingTransition(
R.anim.move_bottom_in,?R.anim.move_top_out);
}?catch?(Exception?e)?{
e.printStackTrace();
}
}
return?true;
default:
break;
}
return?super.onTouchEvent(ev);
}
其他視具體情況而定,比如listview的最后一條,某中間區域響應拖動的事件:
//true是攔截,false是不攔截。這里只是預處理判斷點擊的位置,不攔截。
@Override
public?boolean?onInterceptTouchEvent(MotionEvent?ev)?{
if?(ev.getAction()?==?MotionEvent.ACTION_DOWN)?{
bConsumeDown?=?false;
int?x?=?(int)?ev.getX();
int?y?=?(int)?ev.getY();
dragSrcPosition?=?pointToPosition(x,?y);
dragSrcPointY?=?y;
if?(dragSrcPosition?==?AdapterView.INVALID_POSITION)?{
return?super.onInterceptTouchEvent(ev);
}
FTLog.d(_TAG,?"x="?+?x?+?",y="?+?y);
FTLog.d(_TAG,?"dragSrcPosition=="?+?dragSrcPosition
+?"getAdapter().getCount()=="?+?getAdapter().getCount());
if?(dragSrcPosition?==?getAdapter().getCount()?-?1
||?dragSrcPosition?==?getAdapter().getCount()?-?2)
{//?最后一條是footer,倒數第二條是數據
ViewGroup?itemView?=?(ViewGroup)?getChildAt(dragSrcPosition
-?getFirstVisiblePosition());
int?itemLeft?=?itemView.getLeft();
int?itemRight?=?itemView.getRight();
int?itemMid?=?(itemRight?+?itemLeft)?/?2;
FTLog.d(_TAG,?"itemLeft=="?+?itemLeft?+?",?itemRight="
+?itemRight?+?",itemMid="?+?itemMid);
if?(x?>?itemMid?-?60?&&?x?
bConsumeDown?=?true;//預處理,判斷是點擊觸發拖動的區域,并不攔截事件
return?false;
}
}
}
return?super.onInterceptTouchEvent(ev);
}
/**
*?觸摸事件
*/
@Override
public?boolean?onTouchEvent(MotionEvent?ev)?{
if?(bConsumeDown?==?true?&&?dragSrcPosition?!=?INVALID_POSITION)?{
//只有判斷是點擊觸發拖動的區域時,才進行處理。否則不處理,交予FTBounceListView舊邏輯處理。
int?action?=?ev.getAction();
switch?(action)?{
case?MotionEvent.ACTION_DOWN:
//FTLog.e("TMS===down==",?"tms");
//bConsumeDown?=?true;
break;
//case?MotionEvent.ACTION_MOVE:
//FTLog.e("TMS===move==",?"tms");
//if?(bConsumeDown?==?false)
//{
//super.onTouchEvent(ev);
//}
//break;
case?MotionEvent.ACTION_UP:
FTLog.d(_TAG,?"x="+ev.getX()+",y="+ev.getY());
if?(ev.getY()?
{//向上拖動距離超過20dip,才finish,動畫效果。
try?{
((Activity)?context).finish();
((Activity)?context).overridePendingTransition(
R.anim.move_bottom_in,?R.anim.move_top_out);
}?catch?(Exception?e)?{
e.printStackTrace();
}
}
break;
default:
break;
}
return?true;
}
return?super.onTouchEvent(ev);
}
以上重寫ViewGroup的兩個方法,對于具體的View來講,可以setOnTouchLinstener方法,再其OnTouch方法中,用mGestureDetectorOpen.onTouchEvent(event);來響應。
_imageview_room_op_item_open.setOnTouchListener(new?OnTouchListener()?{
@Override
public?boolean?onTouch(View?v,?MotionEvent?event)?{
mGestureDetectorOpen.onTouchEvent(event);
return?true;
}
});
mGestureDetectorOpen?=?new?GestureDetector(this,?new?OnGestureListener()
{
@Override
public?boolean?onFling(MotionEvent?e1,?MotionEvent?e2,?float?velocityX,
float?velocityY)?{//判斷在_imageview_room_op_item_open控件上移動的距離,do?something}
}
總結
以上是生活随笔為你收集整理的android layout 点击,Tips_Android点击事件(Down、Move、Up)的分发_重写Layout响应拖动事件...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 编程博客,Linux系统编程
- 下一篇: android 百度大头针,百度地图所有