您的位置:首页 > 移动开发 > Android开发

android中onInterceptTouchEvent()方法详解

2015-11-18 12:13 483 查看
这个方法其实以前不怎么关注,后来自定义布局用的多了,发现很多时候都必须要重载这个函数,

一般重载这个函数地方就是你自定义了一个布局,extends LinearLayout等等布局

一般除了自己的业务处理外,返回值只有两种,

第一种:让父类去处理 返回值,跟踪android源码你会知道返回的是false

作用:让自定义布局上面的所有子view 例如button imageview 等可以被点击

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
downX = (int) ev.getX();
downY = (int) ev.getY();
windowX = (int) ev.getX();
windowY = (int) ev.getY();
setOnItemClickListener(ev);
}
return super.onInterceptTouchEvent(ev);
}


第二种:直接返回true

作用:让自定义布局上面的所有子view不可以被点击

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}


关于这个函数的验证我觉得借用大牛的比较好,如果你想确认这个过程的话,自己再敲一遍,很快就搞定了,我已经搞过

地址:http://blog.csdn.net/vipzjyno1/article/details/21746311

首先我们来自定义一个布局,命名为MyLayout,继承自LinearLayout,如下所示:

[java] view
plaincopy

public class MyLayout extends LinearLayout {

public MyLayout(Context context, AttributeSet attrs) {

super(context, attrs);

}

}

然后,打开主布局文件activity_main.xml,在其中加入我们自定义的布局:

[html] view
plaincopy

<com.example.viewgrouptouchevent.MyLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/my_layout"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical" >

<Button

android:id="@+id/button1"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="Button1" />

<Button

android:id="@+id/button2"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="Button2" />

</com.example.viewgrouptouchevent.MyLayout>

可以看到,我们在MyLayout中添加了两个按钮,接着在MainActivity中为这两个按钮和MyLayout都注册了监听事件:

[java] view
plaincopy

myLayout.setOnTouchListener(new OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

Log.d("TAG", "myLayout on touch");

return false;

}

});

button1.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

Log.d("TAG", "You clicked button1");

}

});

button2.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

Log.d("TAG", "You clicked button2");

}

});

我们在MyLayout的onTouch方法,和Button1、Button2的onClick方法中都打印了一句话。现在运行一下项目,效果图如下所示:



分别点击一下Button1、Button2和空白区域,打印结果如下所示:



你会发现,当点击按钮的时候,MyLayout注册的onTouch方法并不会执行,只有点击空白区域的时候才会执行该方法。你可以先理解成Button的onClick方法将事件消费掉了,因此事件不会再继续向下传递。

那就说明Android中的touch事件是先传递到View,再传递到ViewGroup的?现在下结论还未免过早了,让我们再来做一个实验。

查阅文档可以看到,ViewGroup中有一个onInterceptTouchEvent方法,我们来看一下这个方法的源码:

[java] view
plaincopy

/**

* Implement this method to intercept all touch screen motion events. This

* allows you to watch events as they are dispatched to your children, and

* take ownership of the current gesture at any point.

*

* <p>Using this function takes some care, as it has a fairly complicated

* interaction with {@link View#onTouchEvent(MotionEvent)

* View.onTouchEvent(MotionEvent)}, and using it requires implementing

* that method as well as this one in the correct way. Events will be

* received in the following order:

*

* <ol>

* <li> You will receive the down event here.

* <li> The down event will be handled either by a child of this view

* group, or given to your own onTouchEvent() method to handle; this means

* you should implement onTouchEvent() to return true, so you will

* continue to see the rest of the gesture (instead of looking for

* a parent view to handle it). Also, by returning true from

* onTouchEvent(), you will not receive any following

* events in onInterceptTouchEvent() and all touch processing must

* happen in onTouchEvent() like normal.

* <li> For as long as you return false from this function, each following

* event (up to and including the final up) will be delivered first here

* and then to the target's onTouchEvent().

* <li> If you return true from here, you will not receive any

* following events: the target view will receive the same event but

* with the action {@link MotionEvent#ACTION_CANCEL}, and all further

* events will be delivered to your onTouchEvent() method and no longer

* appear here.

* </ol>

*

* @param ev The motion event being dispatched down the hierarchy.

* @return Return true to steal motion events from the children and have

* them dispatched to this ViewGroup through onTouchEvent().

* The current target will receive an ACTION_CANCEL event, and no further

* messages will be delivered here.

*/

public boolean onInterceptTouchEvent(MotionEvent ev) {

return false;

}

如果不看源码你还真可能被这注释吓到了,这么长的英文注释看得头都大了。可是源码竟然如此简单!只有一行代码,返回了一个false!

好吧,既然是布尔型的返回,那么只有两种可能,我们在MyLayout中重写这个方法,然后返回一个true试试,代码如下所示:

[java] view
plaincopy

public class MyLayout extends LinearLayout {

public MyLayout(Context context, AttributeSet attrs) {

super(context, attrs);

}

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

return true;

}

}

现在再次运行项目,然后分别Button1、Button2和空白区域,打印结果如下所示:



你会发现,不管你点击哪里,永远都只会触发MyLayout的touch事件了,按钮的点击事件完全被屏蔽掉了!

看到这里,我相信你对这个函数应该已经的差不多了,
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: