android viewgroup 事件,Android ViewGroup的事件分发分析(上)

最近在查阅Android View的事件分发相关的知识,经过从网上查找和自己查阅相关源码,最终以一个Demo的形势分析下ViewGroup事件分发相关的知识点(感谢鸿神Android ViewGroup事件分发机制)。下面进入正题。先自定义一个按钮和一个ViewGroup中中见代码

.MyButton.java代码

public class MyButton extends android.support.v7.widget.AppCompatButton {

private String TAG = getClass().getSimpleName();

public MyButton(Context context) {

this(context,null);

}

public MyButton(Context context, AttributeSet attrs) {

this(context, attrs,0);

}

public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()){

case MotionEvent.ACTION_DOWN:

Log.e(TAG,"onTouchEvent down");

break;

case MotionEvent.ACTION_UP:

Log.e(TAG,"onTouchEvent up");

break;

case MotionEvent.ACTION_MOVE:

Log.e(TAG,"onTouchEvent move");

break;

}

return super.onTouchEvent(event);

}

@Override

public boolean dispatchTouchEvent(MotionEvent event) {

//防止父控件拦截事件

//getParent().requestDisallowInterceptTouchEvent(true);

switch (event.getAction()){

case MotionEvent.ACTION_DOWN:

Log.e(TAG,"dispatchTouchEvent down");

break;

case MotionEvent.ACTION_UP:

Log.e(TAG,"dispatchTouchEvent up");

break;

case MotionEvent.ACTION_MOVE:

Log.e(TAG,"dispatchTouchEvent move");

break;

}

return super.dispatchTouchEvent(event);

}

}

为myButton的类主要就重写了dispatchTouchEvent和的的onTouchEvent方法,这两个方法就是查看事件分法相关的主要方法

.Mylly.java

public class MyLly extends LinearLayout {

private String TAG = getClass().getSimpleName();

public MyLly(Context context) {

super(context);

}

public MyLly(Context context, @Nullable AttributeSet attrs) {

super(context, attrs);

}

public MyLly(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

}

@Override

public boolean dispatchTouchEvent(MotionEvent event) {

switch (event.getAction()){

case MotionEvent.ACTION_DOWN:

Log.e(TAG,"LinearLayout dispatchTouchEvent down");

break;

case MotionEvent.ACTION_UP:

Log.e(TAG,"LinearLayout dispatchTouchEvent up");

break;

case MotionEvent.ACTION_MOVE:

Log.e(TAG,"LinearLayout dispatchTouchEvent move");

break;

}

return super.dispatchTouchEvent(event);

}

@Override

public boolean onInterceptTouchEvent(MotionEvent event) {

boolean result = false;

switch (event.getAction()){

case MotionEvent.ACTION_DOWN:

//拦截事件的向下传递,自身的onTouchEvent处理事件

//result=true;

Log.e(TAG,"LinearLayout onInterceptTouchEvent down");

break;

case MotionEvent.ACTION_UP:

Log.e(TAG,"LinearLayout onInterceptTouchEvent up");

break;

case MotionEvent.ACTION_MOVE:

Log.e(TAG,"LinearLayout onInterceptTouchEvent move");

break;

}

return result;

}

@Override

public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()){

case MotionEvent.ACTION_DOWN:

Log.e(TAG,"LinearLayout onTouchEvent down");

break;

case MotionEvent.ACTION_UP:

Log.e(TAG,"LinearLayout onTouchEvent up");

break;

case MotionEvent.ACTION_MOVE:

Log.e(TAG,"LinearLayout onTouchEvent move");

break;

}

return super.onTouchEvent(event);

}

}

Mylly继承了的的LinearLayout中是个ViewGroup中中中,主要重写了dispatchTouchEvent,onInterceptTouchEvent和的的的onTouchEvent方法,这第几个是方法是一个一个ViewGroup中事件分法的相关方法。

下面请看MainActivity,具体的分析我们从这里开始。

public class MainActivity extends AppCompatActivity{

private String TAG = "MyButton";

Button myButton;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//给Mylly设置onclick

findViewById(R.id.lly).setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Toast.makeText(MainActivity.this,"click",Toast.LENGTH_LONG).show();

}

});

myButton = findViewById(R.id.btn);

//给myButton设置OnClickListener

myButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Toast.makeText(MainActivity.this,"onClick",Toast.LENGTH_LONG).show();

}

});

//给myButton设置OnLongClickListener

myButton.setOnLongClickListener(new View.OnLongClickListener() {

@Override

public boolean onLongClick(View v) {

Toast.makeText(MainActivity.this,"onLongClick",Toast.LENGTH_LONG).show();

return false;

}

});

}

}

XML文件

xmlns:custom="http://schemas.android.com/apk/res-auto"

android:id="@+id/lly"

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

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity">

android:layout_width="200dp"

android:layout_height="100dp"

android:background="#ff00ff"

android:gravity="center"

android:text="click me"

android:id="@+id/btn"

/>

在MainActivity里我们主要做了三件事,

1,给MyLly根布局添加的点击事件

2,给按钮设置的点击事件

3,给按钮设置的长按事件

在这里我们先分析点击事件

请问程序运行起来后,我点击一下按钮会有什么样的效果呢,是执行了mylly的的的的onClick还是执行了按钮的的的的onClick还是两个都执行呢。我们一起看看效果吧。

7c90a94e913eaf911835b8bb59ea82cd.gif

gif5新文件.gif注意:注意注意

最终是执行了按钮的点击事件,在看下的logcat中的看看事件执行顺序从中找到答案吧。

f113d83e43e9bd135bf9687485a34290.png

WX20180726-162819@2x.png

从日志中可以看到事件的执行顺序为

ViewGroup中的dispatchTouchEvent ----->的ViewGroup的onInterceptTouchEvent ---->按钮的dispatchTouchEvent ---->按钮的的onTouchEvent。

首先我们查看的一个ViewGroup中的dispatchTouchEvent方法

c4387d13e88a1b31a538539c036bd7c4.png

WX20180726-164252@2x.png

2e1c285ad5a448b0c78d01d72c32a7b1.png

WX20180726-164316@2x.png

查看25行当触发ACTION_DOWN的时候,会调用onInterceptTouchEvent获取是否被拦截,这里我们是假,然后在46行省略部分查找消费事件的目标视图具体看源码。找到后在76行会调用dispatchTransformedTouchEvent,

68a129acf914b8630f3b3316805dfb8b.png

image.png

也就是调用我们这个程序中按钮的dispatchTouchEvent。到这里也就是这个程序为什么没有调用Mylly的的的onclick的答案了,因为事件被传递到了目标子查看中,我们打开按钮的dispatchTouchEvent方法。

cf286073484c1acb0306754ad62c038c.png

image.png

先是在30行调用了onTouch方法,如果设置了OntouchListener并且返回了真后面的事件也就不会执行了,这里我们没有为按钮设置OnTouchListener所以会执行34行,进入的的onTouchEvent方法。

我们直接说重点代码。

a1d41b4b8bb05ec8c8662ff8cc48bdb8.png

image.png

会开启一个延时100毫秒的主题

d9efe2287698a370349801d0da433eb3.png

image.png

的100毫秒后还会再开启一个500-100的延时线程

f8c796ea89d2a8442e582ba8cb6289dc.png

image.png

8a980dcdff31f673574e38985f28cef6.png

image.png

在这里会执行performLongClick这个是干什么的呢?进去看看就明白了。一层层进入最终到达这里。

51e94706878f72a5aac4714c9bb7d1a1.png

image.png

也说是如果我们给按钮设置了长按事件,这里就行调用。注意它的返回值是布尔类型。最后我们来看看ACTION_UP,看看代码

e091fb2ab9f694174f3f90c162e95186.png

image.png

打开performClick其它就是执行了我们设置的OnClicklistener的的的的onClick方法。

到此我们解决了为什么最终会调用MyButton的点击方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值