Android TouchEvent事件

来源:互联网 发布:2016知乎年度吐槽精选3 编辑:程序博客网 时间:2024/06/05 02:51

Android TouchEvent事件

1、TouchEvent

在TouchEvent操作里有几种手势,DOWN(按下)、UP(抬起)、MOVE(移动)和Cancel(取消)等。

所有的操作都会在Activity、View和ViewGroup中处理。
在View和Activity中,有两个方法dispatchTouchEvent和onTouchEvent,在ViewGroup中添加了另外一个方法onInterceptTouchEvent。

2、Event流程

假如在一个Activity里面有一个ViewGroup,ViewGroup里面包含一个TextView,点击TextView后会发出TouchEvent事件,每个事件都会以ACTION_DOWN开始,ACTION_UP结束,在中间会有ACTION_MOVE、ACTION_CANCEL等。
  • 每次ACTION DOWN,会调用dispatchTouchEvent,从Activity->ViewGroup->View,一层层往下传递。在View的dispatchTouchEvent中调用onTouchEvent,返回false的话,往上传递给ViewGroup和Activity,依次调用onTouchEvent。
  • 如果DOWN没有在View或ViewGroup中没有处理,Activity将在onTouchEvent中处理接下来的所有事件。如果DOWN在View或ViewGroup处理,但没有处理其他ACTION,Activity依然会调用onTouchEvent。
  • 如果在View的dispatchTouchEvent或者onTouchEvent里面返回true,表明View将处理Action,不会调用ViewGroup和Activy的onTouchEvent。其它Action先在View的onTouchEvent中处理。未处理的Action交给Activity。
  • 如果在ViewGroup的dispatchTouchEvent或者onTouchEvent里面返回true,表明ViewGroup将处理Action。接下来的Action先在ViewGroup中的onTouchEvent中处理。未处理的Action交给Activity。
  • 在ViewGroup中会先调用onInterceptTouchEvent过滤,然后才会传递给View。如果ViewGroup的onInterceptTouchEvent返回true,直接调用ViewGroup的onTouchEvent。onInterceptTouchEvent只会调用一次。
  • 如果View中处理了DOWN,在其它Action时ViewGroup的onInterceptTouchEvent返回true,则会传递CANCEL给View,接下来的Action都会调用ViewGroup的onTouchEvent处理。未处理的Action交给Activity。

3、测试代码

public class TouchEventActivity extends Activity {private final static String LOGTAG = "TouchEventActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_touch);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {LogUtil.log(LOGTAG, "before dispatchTouchEvent " + event.getAction());boolean handle = super.dispatchTouchEvent(event);LogUtil.log(LOGTAG, "after dispatchTouchEvent");return handle;}@Overridepublic boolean onTouchEvent(MotionEvent event) {LogUtil.log(LOGTAG, "before onTouchEvent " + event.getAction());boolean handle = super.onTouchEvent(event);LogUtil.log(LOGTAG, "after onTouchEvent");return handle;}}public class CTouchRelativeLayout extends RelativeLayout {private final static String LOGTAG = "CTouchRelativeLayout";public CTouchRelativeLayout(Context context) {super(context);}public CTouchRelativeLayout(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {LogUtil.log(LOGTAG, "before dispatchTouchEvent " + event.getAction());boolean handle = super.dispatchTouchEvent(event);LogUtil.log(LOGTAG, "after dispatchTouchEvent");return handle;}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {LogUtil.log(LOGTAG, "before onInterceptTouchEvent " + ev.getAction());boolean handle = super.onInterceptTouchEvent(ev);LogUtil.log(LOGTAG, "after onInterceptTouchEvent");return handle;}@Overridepublic boolean onTouchEvent(MotionEvent event) {LogUtil.log(LOGTAG, "before onTouchEvent " + event.getAction());boolean handle = super.onTouchEvent(event);LogUtil.log(LOGTAG, "after onTouchEvent");return handle;}}public class CTouchTextView extends TextView {private final static String LOGTAG = "CTouchTextView";public CTouchTextView(Context context) {super(context);}public CTouchTextView(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {LogUtil.log(LOGTAG, "before dispatchTouchEvent " + event.getAction());boolean handle = super.dispatchTouchEvent(event);LogUtil.log(LOGTAG, "after dispatchTouchEvent");return handle;//if (event.getAction() == MotionEvent.ACTION_DOWN) {//return true;//} else {//return false;//}}@Overridepublic boolean onTouchEvent(MotionEvent event) {LogUtil.log(LOGTAG, "before onTouchEvent " + event.getAction());boolean handle = super.onTouchEvent(event);LogUtil.log(LOGTAG, "after onTouchEvent");//if (event.getAction() == MotionEvent.ACTION_DOWN) {//return true;//} else {//return false;//}return handle;}}

4、布局文件

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:background="#ffffffff" >    <com.blog.demo.control.CTouchRelativeLayout        android:id="@+id/touch_rl"        android:layout_width="240dp"        android:layout_height="300dp"        android:layout_centerInParent="true"        android:background="#ffff0000" >        <com.blog.demo.control.CTouchTextView        android:id="@+id/touch_tv"         android:layout_width="120dp"        android:layout_height="150dp"        android:layout_centerInParent="true"        android:background="#ff0000ff" />        </com.blog.demo.control.CTouchRelativeLayout>    </RelativeLayout>

5、总结

  • 没有处理的事件都会在Activity的onTouch中处理。
  • DOWN事件在哪里处理,接下来的ACTION都只会传递到那里。
  • 如果ViewGroup中的onInterceptTouchEvent返回true,事件将不会再往下传递。onInterceptTouchEvent返回true后不会再次调用。
  • 如果ViewGroup的子控件在DOWN时处理了事件,那么在onInterceptTouchEvent返回true后代替子控件处理Action。

6、OnTouchListener

View可以添加TouchEvent监听器,使用setOnTouchListener方法添加。在dispatchTouchEvent中,先调用OnTouchListener的onTouch。如果返回true,返回到上一层,否则调用onTouchEvent。
0 0