Activity事件分发,View和ViewGroup

> View和ViewGroup

-- ViewGroup的相关事件有三个:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent;
View的相关事件只有两个:dispatchTouchEvent、onTouchEvent。

-- View体系的绘制流程是从ViewRootImpl的performTraversals方法开始的;
View的测量大小流程:performMeasure –> measure –> onMeasure等方法;
View的测量位置流程:performLayout –> layout –> onLayout等方法;

View的绘制流程:performDraw-> draw-> onDraw等方法;
-- View.java
public boolean dispatchTouchEvent(MotionEvent event)
public boolean onTouchEvent(MotionEvent event) 


 public class TestButton extends Button {

    public TestButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.i("TestButton", "dispatchTouchEvent    action = " + event.getAction());
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i("TestButton", "onTouchEvent    action = " + event.getAction());
        return super.onTouchEvent(event);
    }
}

-- ViewGroup.java
public boolean dispatchTouchEvent(MotionEvent event)
public boolean onTouchEvent(MotionEvent event) 
public boolean onInterceptTouchEvent(MotionEvent event)


 public class TestLinearLayout extends LinearLayout {

    public TestLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.d("TestLinerLayout", "onInterceptTouchEvent    action = " + ev.getAction());
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.d("TestLinerLayout", "dispatchTouchEvent    action = " + ev.getAction());
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("TestLinerLayout", "onTouchEvent    action = " + event.getAction());
        return super.onTouchEvent(event);
    }
}

> Activity事件分发
public class MainActivity extends Activity {
    private RTButton button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
          System.out.println("Activity---dispatchTouchEvent---DOWN");
          break;
        case MotionEvent.ACTION_MOVE:
              System.out.println("Activity---dispatchTouchEvent---MOVE");
          break;
        case MotionEvent.ACTION_UP:
          System.out.println("Activity---dispatchTouchEvent---UP");
          break;
        default:
          break;
        }
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
          System.out.println("Activity---onTouchEvent---DOWN");
          break;
        case MotionEvent.ACTION_MOVE:
          System.out.println("Activity---onTouchEvent---MOVE");
          break;
        case MotionEvent.ACTION_UP:
          System.out.println("Activity---onTouchEvent---UP");
          break;
        default:
          break;
        }
        return super.onTouchEvent(event);
    }
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("MainActivity", "onTouch    action = "+event.getAction() + v);
        return false;
    }

}


 ((ViewGroup)getWindow().getDecorView().findViewById(android.R.id.content)).getChildAt(0)这种方式获取Activity所设置的View。这个mDecor显然就是getWindow().getDecorView()返回的View,而我们通过setContentView设置的View是它的一个子View。

  dispatchTouchEvent (Activity) ->是否超出Activity所属的Window边界 (Activity) -> superDispatchTouchEvent (Window abstract class) -> superDispatchTouchEvent(PhoneWindow) -> superDispatchTouchEvent(DecorView) -> dispatchTouchEvent(ViewGroup FrameLayout)

> Android事件分发机制

-- Android事件分发机制主要由“事件分发”—>“事件拦截”—>“事件响应”这三步来进行逻辑控制的。
2.1 事件分发:public boolean dispatchTouchEvent(MotionEvent ev)
 当监听到有触发事件时,首先由Activity进行捕获,然后事件就进入事件分发的流程。Activity本身没有事件拦截,从而将事件传递给最外层的View的dispatchTouchEvent(MotionEvent ev)方法,该方法将对事件进行分发。
 return true : View消费所有事件。
 return false :停止分发,交由上层控件的onTouchEvent方法进行消费,如果本层控件是Activity,那么事件将被系统消费、处理。
super.dispatchTouchEvent(ev): 将事件交由本层的事件拦截onInterceptTouchEvent方法处理。

2.2 事件拦截:public boolean onInterceptTouchEvent(MotionEvent ev)
 return true: 对事件拦截,交由本层的onTouchEvent进行处理。
 return false: 不拦截,分发到子View,由子View的dispatchTouchEvent方法处理。
 super.onInterceptTouchEvent(ev):默认表示事件拦截,交由本层的onTouchEvent进行处理。

2.3 事件响应:public boolean onTouchEvent(MotionEvent ev)
 return true: 表示onTouchEvent处理完事件后消费了此次事件。
 return false: 不响应事件,不断的传递给上层的onTouchEvent方法处理,直到某个View的onTouchEvent返回true,则认为该事件被消费。如果到最顶层View还是返回false,那么该事件不消费,将交由Activity的onTouchEvent进行处理。
 return: super.onTouchEvent,不响应事件,结果与return返回false一样。

-- Android的分发机制:
 1.ViewGroup默认不拦截任何事件。
 2.点击事件的分发过程如下:dispatchTouchEvent—>onTouchListener的OnTouch方法—>onTouchEvent—>onClickListener的onClick方法。从而也可以看出onTouch优先于onClick执行。
 3.子View可以通过使用getParent().requestDisallowInterceptTouchEvent(true),阻止ViewGroup对其MOVE或UP事件进行拦截。
 4.一个点击事件产生后,传递过程是:Activity—>Window—>View。顶级View接受到事件后,就会按照上面的规则去分发事件。

-- 事件传递的顺序:Activity -> ViewGroup -> View
 

猜你喜欢

转载自blog.csdn.net/ShareUs/article/details/81607463