本帖最后由 大山哥哥 于 2017-4-30 23:39 编辑
上一篇我们分析了Android事件分发的最基本的传递过程。也就是每一层都不处理也不拦截的传递过程。接下来我们就一块来分析一下。如果其中某层有拦截或者有处理的时候,事件是如何传递的。
为了大家查看方便。我们还是先把自定义控件的代码放到这里。这次,我们把MyFrameLayout和MyLinearLayout的onInterceptTouchEvent中返回true。看一下事件是如何传递的。
[AppleScript] 纯文本查看 复制代码 package com.itheima.touchdemo;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
public class MyFrameLayout extends FrameLayout {
public MyFrameLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public MyFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public MyFrameLayout(Context context) {
super(context);
}
// 事件处理
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("FrameLayout---->onTouchEvent---start");
boolean b = super.onTouchEvent(event);
System.out.println("FrameLayout---->onTouchEvent---end---" + b);
return b;
}
// 事件拦截
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
System.out.println("FrameLayout---->onInterceptTouchEvent---start");
boolean b = true;
System.out.println("FrameLayout---->onInterceptTouchEvent---end---" +b);
return b;
}
// 事件分发
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
System.out.println(ev.getX() + "----- " + ev.getY());
System.out.println("FrameLayout---->dispatchTouchEvent---start");
boolean b = super.dispatchTouchEvent(ev);
System.out.println("FrameLayout---->dispatchTouchEvent---end--->" + b);
return b;
}
}
同理自定义MyLinearLayout,并重写三个方法便于观察你:
[AppleScript] 纯文本查看 复制代码 package com.itheima.touchdemo;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.LinearLayout;
public class MyLinearLayout extends LinearLayout {
public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public MyLinearLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
// 事件处理
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("LinearLayout---->onTouchEvent---start");
boolean b = super.onTouchEvent(event);
System.out.println("LinearLayout---->onTouchEvent---end---" + b);
return b;
}
// 事件拦截
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
System.out.println("LinearLayout---->onInterceptTouchEvent---start");
boolean b = true;
System.out.println("LinearLayout---->onInterceptTouchEvent---end---" +b);
return b;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
System.out.println("LinearLayout---->dispatchTouchEvent---start");
boolean b = super.dispatchTouchEvent(ev);
System.out.println("LinearLayout---->dispatchTouchEvent---end--->" + b);
return b;
}
}
自定义MyView,重写dispatchTouchEvent,onTouchEvent两个方法,并添加日志便于观察:
[AppleScript] 纯文本查看 复制代码 package com.itheima.touchdemo;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class MyView extends View {
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public MyView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
// 事件处理
@Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("View---->onTouchEvent---start");
boolean b = super.onTouchEvent(event);
System.out.println("View---->onTouchEvent---end---" + b);
return b;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
System.out.println("View---->dispatchTouchEvent---start");
boolean b = super.dispatchTouchEvent(ev);
System.out.println("View---->dispatchTouchEvent---end--->" + b);
return b;
}
}
Activity中初始化view时,动态将三个View依次嵌套起来:
[AppleScript] 纯文本查看 复制代码 package com.itheima.touchdemo;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = init_view();
setContentView(view);
}
private View init_view() {
MyFrameLayout myFrameLayout = new MyFrameLayout(this);
myFrameLayout.setBackgroundColor(Color.RED);
MyLinearLayout myLinearLayout = new MyLinearLayout(this);
myLinearLayout.setBackgroundColor(Color.GREEN);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(200, 200);
params.gravity = Gravity.CENTER;
myFrameLayout.addView(myLinearLayout, params);
MyView myView = new MyView(this);
myView.setBackgroundColor(Color.GRAY);
LinearLayout.LayoutParams params1 = new LinearLayout.LayoutParams(100, 100);
params1.gravity = Gravity.CENTER_VERTICAL;
myLinearLayout.setGravity(Gravity.CENTER);
myLinearLayout.addView(myView,params1);
// FrameLayout.LayoutParams params2 = new FrameLayout.LayoutParams(100,
// 100);
// params2.gravity = Gravity.CENTER;
// myFrameLayout.setGravity(Gravity.CENTER);
// myFrameLayout.addView(myView, params2);
return myFrameLayout;
}
}
红色的是MyFrameLayout,绿色的是MyLInearLayout,灰色的是MyView。现在我将手指按在灰色的区域按下时,事件的传递过程是这样的:
[AppleScript] 纯文本查看 复制代码 I/System.out: FrameLayout---->dispatchTouchEvent---start
I/System.out: FrameLayout---->onInterceptTouchEvent---start
I/System.out: FrameLayout---->onInterceptTouchEvent---end---true
I/System.out: FrameLayout---->onTouchEvent---start
I/System.out: FrameLayout---->onTouchEvent---end---false
I/System.out: FrameLayout---->dispatchTouchEvent---end--->false
因为最外成的MyFrameLayout中的onInterceptTouchEvent中返回了true。所以事件被MyFrameLayout拦截。事件不会再往下传递。MyFrameLayout拦截之后,会问自己的onTouchEvent,看自己处理不处理。onTouchEvent中返回的是flase,不处理。所以up事件都不会传递到MyFrameLayout中。
如果我们只在MyFrameLayout和MyLinearLayoutdeonTouchEvent中返回true。事件又是如何传递的呢?
down事件的log:
[AppleScript] 纯文本查看 复制代码 04-30 15:36:16.075 2367-2367/com.itheima.touchdemo I/System.out: FrameLayout---->dispatchTouchEvent---start
04-30 15:36:16.075 2367-2367/com.itheima.touchdemo I/System.out: FrameLayout---->onInterceptTouchEvent---start
04-30 15:36:16.075 2367-2367/com.itheima.touchdemo I/System.out: FrameLayout---->onInterceptTouchEvent---end---false
04-30 15:36:16.075 2367-2367/com.itheima.touchdemo I/System.out: LinearLayout---->dispatchTouchEvent---start
04-30 15:36:16.075 2367-2367/com.itheima.touchdemo I/System.out: LinearLayout---->onInterceptTouchEvent---start
04-30 15:36:16.076 2367-2367/com.itheima.touchdemo I/System.out: LinearLayout---->onInterceptTouchEvent---end---false
04-30 15:36:16.076 2367-2367/com.itheima.touchdemo I/System.out: View---->dispatchTouchEvent---start
04-30 15:36:16.076 2367-2367/com.itheima.touchdemo I/System.out: View---->onTouchEvent---start
04-30 15:36:16.076 2367-2367/com.itheima.touchdemo I/System.out: View---->onTouchEvent---end---false
04-30 15:36:16.076 2367-2367/com.itheima.touchdemo I/System.out: View---->dispatchTouchEvent---end--->false
04-30 15:36:16.076 2367-2367/com.itheima.touchdemo I/System.out: LinearLayout---->onTouchEvent---start
04-30 15:36:16.076 2367-2367/com.itheima.touchdemo I/System.out: LinearLayout---->onTouchEvent---end---true
04-30 15:36:16.076 2367-2367/com.itheima.touchdemo I/System.out: LinearLayout---->dispatchTouchEvent---end--->true
04-30 15:36:16.076 2367-2367/com.itheima.touchdemo I/System.out: FrameLayout---->dispatchTouchEvent---end--->true
up事件log:
[AppleScript] 纯文本查看 复制代码 04-30 15:36:39.106 2367-2367/com.itheima.touchdemo I/System.out: FrameLayout---->dispatchTouchEvent---start
04-30 15:36:39.107 2367-2367/com.itheima.touchdemo I/System.out: FrameLayout---->onInterceptTouchEvent---start
04-30 15:36:39.107 2367-2367/com.itheima.touchdemo I/System.out: FrameLayout---->onInterceptTouchEvent---end---false
04-30 15:36:39.107 2367-2367/com.itheima.touchdemo I/System.out: LinearLayout---->dispatchTouchEvent---start
04-30 15:36:39.107 2367-2367/com.itheima.touchdemo I/System.out: LinearLayout---->onTouchEvent---start
04-30 15:36:39.107 2367-2367/com.itheima.touchdemo I/System.out: LinearLayout---->onTouchEvent---end---true
04-30 15:36:39.107 2367-2367/com.itheima.touchdemo I/System.out: LinearLayout---->dispatchTouchEvent---end--->true
04-30 15:36:39.107 2367-2367/com.itheima.touchdemo I/System.out: FrameLayout---->dispatchTouchEvent---end--->true
总结一下:
如果同时在onInterceptTouchEvent中返回true。谁在最外层,谁先处理事件。如果同时在onTouchEvent中返回true。谁在最里层谁先处理事件。
|