android 中的事件分发和事件拦截

Android 面试:事件分发8连问 /stage赋值操作if(stage!}else{try{如上所示:1.是一种输入事件,链表结构,遍历传递给InputStage2.InputStage是处理输入的责任链,在调用deliver时会遍历责任链传递事件3.事件分发完成后会调用,告知进程的线程,最终将该事件移除,完成此次事件的分发消费。那么问题来了,InputStage的责任链是什么时候组件的呢? 阅读详情

 

old 代码:事件分发和事件拦截

 

good : https://www.jianshu.com/p/e99b5e8bd67b

new : https://github.com/kodulf/EventDispatchTestDemo

 

事件分发:
dispathTouchEvent
1. 功能:从当前容器向自己内部的子容器/控件,传递触摸事件;
2. 特点:在传递的时候,会检查,触摸事件是否命中了内部的子控件,如果找到命中的子控件,那么,会调用子控件的 dispatchTouchEvent 方法,让子控件继续传递触摸事件;
3. 当 dispatchTouchEvent 方法找不到命中的子控件时候,当前的控件或者容器自己就进入到 onTouchEvent


onTouchEvent
1. onTouchEvent 如果这个方法,返回true, 这个方法所属的控件,相当于把事件消费掉了;
2. 返回true, 这个控件的父容器以及更上层的父容器都不会再调用 onTouchEvent了;
3. 对于UI结构来说,  onTouchEvent 这个方法,是从最内部子控件开始执行,之后就是每一级的父容器在执行onTouchEvent() ,相当于从最内部调用到最外部。



事件拦截:
拦截就是在容器执行的时候,不再向子控件发送事件
当前的ViewGroup 在进行事件分发的时候,先进行检查,调用自身的 onInterceptTouchEvent, 当这个方法,返回 true的时候,那么ViewGroup 将把事件拦截下来,不再给 自己的子控件发送事件了;


注意:拦截的功能,只有ViewGroup以及子类,容器可以实现拦击;因为ViewGroup的dispatchTouchEvent内部会向子容器和空间发送消息;

其实换个位置思考,如果是View的话,它也没有子控件,它就是最后的那个接受者,就是最后的士兵,它也没有必要拦截.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++

打个比方:事件分发就像是领导分配任务:或者让下面的人交经费。

连长分配任务给排长,

------------ 排长分配任务给班长,

-------------------------班长分配任务给士兵,

-------------------------士兵写报告交给班长,

-----------班长将报告交给排长,

排长将报告交给给连长  

 

分配任务就是dispatchTouchEvent

提交报告就是onTouchEvent 当然有的时候班长收到报告后也可以不给排长,可能这里是什么经费的,自己先用了,哈哈,如果是true的就是自己用了。

如果排长体恤下面的班长,那么他可以不分配任务给下面的人,自己拦截了然后处理了,onInterceptTouchEvent.

如果士兵非要做那么他要提个请求: requestDisallowInterceptTouchEvent

 

 


    /**
     * 如果return true调用自己的onTouchEvent回调
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.d("kodulf", "------- MyLinearLayout onInterceptTouchEvent : ");

        return super.onInterceptTouchEvent(ev);
//        return true;
    }

    /**
     * 如果return true 不会调用自己的onTouchEvent回调
     * @param ev
     * @return
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.d("kodulf", "------- MyLinearLayout dispatchTouchEvent: ");
//        return super.dispatchTouchEvent(ev);
        return true;
    }

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

 

之前的参考记录:

 

 

1:事件分发

Android UI的结构
Android UI内部的坐标
Android UI常见的事件
Android UI事件目标的定位
Android UI事件的传递方式
Android UI事件拦截与分发


2:Android UI结构


修改public class MainActivity extends AppCompatActivity {
到public class MainActivity extends Activity {




点击Monitor
然后点击DDMS左边的有家好的图片,
选择Hierarchy View


MVC
PhoneWindow内部类DecorView
所有的Activity


actionbar 就是ViewStub
setContentView 就是FrameLayout 




现在已经五层了,所以listView 里面需要减少findViewById的次数




2.1 setContentView
public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }


我们可以自己查找一个PhoneWindow
其实也就是getWindow()返回的




PhoneWindow$DecorView 是一个帧布局FrameLayout+++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++
onDestory 就是删除
多了一个activity 就是在这个FrameLayout 上面又加一层
+++++++++++++++++++++++++++++++++++++++++++++++++++++
activity 的回退栈就是在这个FrameLayout 上面添加删除。
+++++++++++++++++++++++++++++++++++++++++++++++++++++




点击的位置,是由硬件传过来的。






event里面的getX 和getY是view 内部的,而不是全部屏幕的。
获取硬件的卓表,需要使用event.getRawX(),event.getRawY();








如果哦人能够起中有一个Button


点击的时候也是一层一级的。
其实大概是是先从DoctView-》contentView-》某个子容器-》button的容器


Android UI基础事件:一共分为四种:
1:MotionEvent:手在屏幕上的操作,也可以认为是是TouchEvent。因为TouchEvent的参数就是MotionEvnet
最重要的就是MotionEvent
2:KeyEvent:键盘事件,DPad(方向键),NumPad(数字键盘),
3:FocusEvent:焦点时间,主要影响了一个空间是否能够接受其他时间
例如键盘事件和触摸事件。谁有焦点,谁就可以接收时间
电视上面用到的比较多。


4:轨迹球的事件
几乎没有了。
----------------------------------------------------------
最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent最重要的就是MotionEvent
--------------------------------------------------------------


onTouchEvent 的ontTouch Down返回true 就是后续的事件我自己处理了,
如果返回false,那么后续的事件交给父容器处理




===============================================================================




Android UI的事件传递啊




<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">




    <TextView android:text="事件传递" android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">


        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="200dp">
            <TextView
                android:id="@+id/txt_click_me"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="点我一下"
                android:textSize="35dp"/>
        </FrameLayout>
    </LinearLayout>
</LinearLayout>


------------------------------------------------------------


public class MainActivity extends Activity implements View.OnTouchListener {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView = (TextView)findViewById(R.id.txt_click_me);
        //接口形式的触摸事件监听
        textView.setOnTouchListener(this);
    }


    /**
     *
     * @param v
     * @param event
     * @return
     */
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //查看一下,onTouch 调用顺序,强制弄一个异常,你怎么这个时候调用关系就出来了e
        int a = 0,b=3;
        try {
            int c=b/3;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}




-------------------------------------------------------------------------
android 中所有的事件都是调用的loop来执行的。


创建一个自定义View LinearLiayout
public class RootLinearLayout extends LinearLayout {
    public RootLinearLayout(Context context) {
        super(context);
    }


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


-----------------------------------------------
public class RootLinearLayout extends LinearLayout {
    public RootLinearLayout(Context context) {
        super(context);
    }


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


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action){
            case MotionEvent.ACTION_DOWN:
                Log.d("151225MY", "dispatchTouchEvent 按下");
        }
        return super.dispatchTouchEvent(ev);
    }
}


直接修改main 里面的首行:




<com.kodulf.uistructdemo.widget.RootLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    
------------------------------------------------
在创建一个自定义View




public class SubLinearLayout extends LinearLayout {
    public SubLinearLayout(Context context) {
        super(context);
    }


    public SubLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action){
            case MotionEvent.ACTION_DOWN:
                Log.d("151225MY", "SubLinearLayout dispatchTouchEvent 按下");
        }
        return super.dispatchTouchEvent(ev);
    }
}




---------------------------------------------------
然后把布局里面的第二个LinearLayout也修改为我们的自定义的View
<com.kodulf.uistructdemo.widget.SubLinearLayout




---------------------------------------------------
public class MyTextView extends TextView{


    public MyTextView(Context context) {
        super(context);
    }


    public MyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action){
            case MotionEvent.ACTION_DOWN:
                Log.d("151225MY", "MyTextView dispatchTouchEvent 按下");
        }
        return super.dispatchTouchEvent(ev);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
       int action = event.getAction();
        switch (action){
            case MotionEvent.ACTION_DOWN:
                Log.d("151225MY", "MyTextView onTouchEvent 按下");
        }
        return super.onTouchEvent(event);
    }
}


--------------------------------------------------------
修改TextView 为<com.kodulf.uistructdemo.widget.MyTextView




最终的xml为:
<com.kodulf.uistructdemo.widget.RootLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"


    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">




    <TextView android:text="事件传递" android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <com.kodulf.uistructdemo.widget.SubLinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
            <com.kodulf.uistructdemo.widget.MyTextView
                android:id="@+id/txt_click_me"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="点我一下"
                android:textSize="35dp"/>


    </com.kodulf.uistructdemo.widget.SubLinearLayout>
</com.kodulf.uistructdemo.widget.RootLinearLayout>
----------------------------------------------------------------


<com.kodulf.uistructdemo.widget.RootLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"


    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"
    android:background="#F00">




    <TextView android:text="事件传递" android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <com.kodulf.uistructdemo.widget.SubLinearLayout
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_marginTop="100dp"
        android:orientation="vertical"
        android:background="#0F0">
            <com.kodulf.uistructdemo.widget.MyTextView
                android:id="@+id/txt_click_me"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="点我一下"
                android:layout_margin="50dp"
                android:textSize="35dp"
                android:background="#00f"/>


    </com.kodulf.uistructdemo.widget.SubLinearLayout>
</com.kodulf.uistructdemo.widget.RootLinearLayout>




-------------------------------------------------------------------


RootLinearyLayout


里面添加:


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        switch (action){
            case MotionEvent.ACTION_DOWN:
                Log.d("151225MY", "RootLineary onTouchEvent 按下");
        }
        return super.onTouchEvent(event);
    }


修改里面的返回值,true 和false 看看区别


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        switch (action){
            case MotionEvent.ACTION_DOWN:
                Log.d("151225MY", "MyTextView onTouchEvent 按下");
        }
        return super.onTouchEvent(event);
    }


-------------------------------------------------------------------


再在SubLinearLayout




然后在修改它的onTouchEvent






dispatchTouchEvent -U型- onTouch




----------------------------------------------------------------------------------------------------------------------
标准时间传递的流程:




事件从最外层传递给内部
最外层 子容器onTouchEvent 返回false,执行最外层的onTouchEvent
   --》子容器 空间返回false,执行子容器onTouchEvent
---》控件 控件onTouchEvent,如果返回true,就是自己处理,如果返回fals

dispatchTouchEvnet 会调用空间内部的onTouchEvent


----------------------------------------------------------------------------------------------------------------------


dispatch 就是分发的意思
dispatch 就是分发的意思
dispatch 就是分发的意思
dispatch 就是分发的意思
dispatch 就是分发的意思
dispatch 就是分发的意思
dispatch 就是分发的意思
dispatch 就是分发的意思
dispatch 就是分发的意思
dispatch 就是分发的意思


--------------------------------------------------------------------------------------
拦截的功能,只有ViewGroup以及子类,容器可以实现拦击;
因为ViewGroup的dispatchTouchEvent内部会向子容器和空间发送消息;


拦截就是在容器执行的时候,不再像子空间发送事件


在SubLinearLayout
    /**
     * 事件拦截操作:返回true,那么所有传给当前容器的事件
     * 都不会再传递给子控件了
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //return super.onInterceptTouchEvent(ev);
        return true;
    }


000000000000000000000000000000000000000000000000000000000000
应用场景:用于解决一些时间的冲突情况的,例如功能的限制;
比如:功能需要登陆才可以使用,如果没有登陆,那么功能全部禁用
000000000000000000000000000000000000000000000000000000000000


如何开启容器的拦截和取消
1:容器内部包含了一个叫做requestDisallowInterceptTouchEvent(true);
2:这个方法,可以让控件的父容器以及更上层的容器都不再拦截事件。


ScrollView 里面套一个ListView


--------------------------------------------------------------






新建


/**
 * Created by Administrator on 15-12-25.
 */
public class MyListView extends ListView {


    public MyListView(Context context) {
        super(context);
    }


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


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action){
            case MotionEvent.ACTION_MOVE:
                Log.d("151225MY", "MYListView dispatchTouchEvent MOVE");
        }
        return super.dispatchTouchEvent(ev);
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action){
            case MotionEvent.ACTION_MOVE:
                Log.d("151225MY", "MYListView onInterceptTouchEvent MOVE");
        }
        return super.onInterceptTouchEvent(ev);
    }
}


新建




/**
 * Created by Administrator on 15-12-25.
 */
public class MyScrollView extends ScrollView {
    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }


    public MyScrollView(Context context) {
        super(context);
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action){
            case MotionEvent.ACTION_MOVE:
                Log.d("151225MY", "MYScrolloView dispatchTouchEvent MOVE");
        }
        return super.dispatchTouchEvent(ev);
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int action = ev.getAction();
        switch (action){
            case MotionEvent.ACTION_MOVE:
                Log.d("151225MY", "MYScrolloView onInterceptTouchEvent MOVE");
        }
        return super.onInterceptTouchEvent(ev);
    }
}


litView中dispatchTouchEvent,
添加requestDisallowIntegceptTouchEvent(true);


但是这个还是有点问题的,


再优化:
listView的高度默认为0,把listView 的设置为wrap_content 就好了。
在listView 里面添加:


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int hMode = MeasureSpec.getMode(heightMeasureSpec);
        int hSize = MeasureSpec.getSize(heightMeasureSpec);


        switch(hMode){
            case MeasureSpec.UNSPECIFIED:
                Log.d("151225MY","hMode UNSPECIFIED");
                break;
            case MeasureSpec.AT_MOST:
                break;
            case MeasureSpec.EXACTLY:
                break;
        }
        Log.d("151225MY","hSize="+hSize);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }




进一步修改;
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int hMode = MeasureSpec.getMode(heightMeasureSpec);
        int hSize = MeasureSpec.getSize(heightMeasureSpec);


        switch(hMode){
            case MeasureSpec.UNSPECIFIED:
                Log.d("151225MY","hMode UNSPECIFIED");
                break;
            case MeasureSpec.AT_MOST:
                break;
            case MeasureSpec.EXACTLY:
                break;
        }
        Log.d("151225MY","hSize="+hSize);


        // ScrollView+ListView 时候,高度模式强制设置为UNSPECIFIED
        //ListView 只会计算一条的高度;
        //将height的模式,强制设置为AT_MOST就会进行计算实际的高度了
        //考虑到ListView条目数量不确定,高度也不确定,height size应该是一个最大值
        heightMeasureSpec=MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE>>2,MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }




-------------------------------------------------------------------------------
新建
public class MyArrayAdapter extends ArrayAdapter<String> {
    public MyArrayAdapter(Context context, int resource, List<String> objects) {
        super(context, resource, objects);
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Log.d("151223MY","postion="+position);
        return super.getView(position, convertView, parent);
    }
}


总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。
总体来说ScrollView 套ListView 是不推荐的。


ViewPager+ViewPager




关于拦截:
1:dispatchTouchEvent 会自动调用拦截方法返回true,拦截事件;
2:如果容器内部的requestDisallowInterceptTouchEvent设置为true,容器不会拦截事件。
3:通常在拦截事件中,进行数值的或者是控件位置的检查,来判断是否拦截事件。之后才是onTouchEvent执行;




新建一个NavigationDrawerActivity


作业:看ViewPager的源码关于onInterceptTouchEvent


++++++++++++++++++++++++++++++++++++++++++++++++
ViewPager+图片放大。。+++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++




取消readme
选择ssh,
复制
打开git bash
git clone git.oschina.net:.....git
open .








 

作业里的:

 

public class MySliding extends SlidingPaneLayout {
    public MySliding(Context context) {
        super(context);
    }

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        boolean ret=false;
        float x = ev.getX();
        int width = getWidth();
        int action = ev.getAction();
        switch (action){
            case MotionEvent.ACTION_DOWN:
                if(x>width/10&&x<width*9/10){
                    ret=false;
                    Log.d("151228MY", "false");
                }else{
                    ret=true;
                    Log.d("151228MY", "true");
                }
                Log.d("151228MY", "x=" + x + " width=" + width + " width/10=" + width / 10+" width*9/10="+width*9/10);
                break;
        }
        return ret;
//        return super.onInterceptTouchEvent(ev);
    }
}

 

 

 


















 

事件分发:
dispathTouchEvent
1. 功能:从当前容器向自己内部的子容器/控件,传递触摸事件;
2. 特点:在传递的时候,会检查,触摸事件是否命中了内部的子控件,如果找到命中的子控件,那么,会调用子控件的 dispatchTouchEvent 方法,让子控件继续传递触摸事件;
3. 当 dispatchTouchEvent 方法找不到命中的子控件时候,当前的控件或者容器自己就进入到 onTouchEvent


onTouchEvent
1. onTouchEvent 如果这个方法,返回true, 这个方法所属的控件,相当于把事件消费掉了;
2. 返回true, 这个控件的父容器以及更上层的父容器都不会再调用 onTouchEvent了;
3. 对于UI结构来说,  onTouchEvent 这个方法,是从最内部子控件开始执行,之后就是每一级的父容器在执行onTouchEvent() ,相当于从最内部调用到最外部。



事件拦截:
拦截就是在容器执行的时候,不再向子控件发送事件
当前的ViewGroup 在进行事件分发的时候,先进行检查,调用自身的 onInterceptTouchEvent, 当这个方法,返回 true的时候,那么ViewGroup 将把事件拦截下来,不再给 自己的子控件发送事件了;


注意:拦截的功能,只有ViewGroup以及子类,容器可以实现拦击;因为ViewGroup的dispatchTouchEvent内部会向子容器和空间发送消息;

 

Android事件拦截 背景 之前有同事吐槽Android的事件分发拦截框架对于事件的拦截的方式和返回值比较乱,不同的地方需要返回不同的值,因此希望撰写一篇文档以作记录。 本文主要分析触摸事件和按键事件在不同阶段被拦截的流程,总结在不同阶段不同方法中返回值的含义。 按键的拦截 interceptKeyBeforeQueueing 在inputflinger分发keyevent前,会先将event上报给PhoneWindownManager处理,如果PhoneWindowManager消费掉,则不会继续分发给应用。这个Ph 阅读详情

相关推荐

Android 面试:事件分发8连问,androidrom移植

} else { return dispatchGenericMotionEvent(event); } } 1.经过层层回调会调用到mView.dispatchPointerEvent 2.我们知道ViewRootImpl中的mView就是DecorView 现在事件已经传递到了DecorView,也就是我们界面的根布局 接下来是事件在Activity,Window,DecorView中的传递 2.4 事件在Activity,Window,DecorView中的传递 //DecorView.java @O

sa3221sa的博客 2960

Android图解浅析事件拦截机制

当Android系统捕获到用户的各种输入事件后,如何准确的传递给真正的需要这个事件的控件?Android提供了一整套完善的事件传递、处理机制,来帮助开发者完成准确的事件分配与处理,这里我就不分析源码了,简单点,图形化分发过程,便于理解,待到后期分析dispatchTouchEvent源码时,回想这个图解,会方便理解很多。 当我们点击一个按钮时,通常会产生两个或者三个事件---按下、滑动(可能无)

gongwq的博客 2102

Android 面试:事件分发8连问,安卓驱动面试

public final class ViewRootImpl { public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { requestLayout(); // … // 创建InputChannel mInputChannel = new InputChannel(); // 通过Binder在SystemServer进程中完成InputChannel的注册 mWindowSessi

m0_66155412的博客 388

【Android】事件的拦截和分发机制

事件的拦截和分发机制

每天不是在写bug就是在写bug的路上 678

Android焦点事件分发与传递机制

Android 焦点事件分发与传递机制

永远不要停下学习的脚步。 8404

Android View 事件分发机制

Android 中的 View 事件分发机制是实现用户交互的核心部分之一,它负责管理事件的传递和处理。理解这一机制对于开发复杂的用户界面至关重要。在本文中,我将详细介绍 Android 中的 View 事件分发机制,包括事件的分发流程、事件类型、ViewGroup 的作用以及通过代码示例演示事件分发过程。

半夏微凉科技 910

Android中级——事件拦截机制和滑动冲突

若MyViewGroupA的onInterceptTouchEvent()方法返回True,打印如下。若MyViewGroupB的onInterceptTouchEvent()方法返回True,打印如下。若MyViewGroupB的onTouchEvent()方法返回True,打印如下。布局如下,MyViewGroupA包裹MyViewGroupB再包裹MyView。若MyView的onTouchEvent()方法返回True,打印如下。点击最内层蓝色的MyView,打印如下。

松仔Log的博客 1233

【开关电源篇】整流及其滤波电路的工作原理和设计指南-超简单解读

半波整流是一种利用二极管的单向导通特性,将交流电转换为直流电的基础电路。它通过“切除”交流电的半个周期,仅保留另外半个周期来实现整流。1 开关电源超快学习思路点击跳转1.1开关电源的原理、结构和实物入门篇-超简单解读点击跳转1.2开关电源的EMI输入电路-超简单解读点击跳转倍压整流适用于需要高电压、小电流的特殊场合,通过电容充放电实现电压倍增。

2301_81299416的博客 2924

Android view 事件分发流程(四)--- 事件拦截

事件拦截就是拦截事件分发到子View中去。事件拦截的方式有两种:内部拦截和外部拦截。move事件 → 子View在dispatchTouchEvent方法中调用getParent().requestDisallowIntercepteTouchEvent(false) → mGroupFlags = 0 → disallowIntercept = false → intercepted = onInterceptTouchEvent(ev);

a18211246446的博客 1245

告别Root!用Termux+ADB在Android上玩转自动化(保姆级教程)

本文详细介绍了如何在非Root环境下使用Termux和ADB实现Android自动化操作,无需Root权限即可运行自动化脚本。通过Termux搭建Linux终端环境,结合ADB无线调试和Python脚本,实现点击、滑动、截图等自动化功能,适用于定时任务、自动签到等场景。

weixin_42548888的博客 536

贴片二极管SOD封装详解:SOD-123/323/523尺寸焊盘设计要点

表面贴装技术中,二极管封装尺寸直接决定PCB布局与焊接可靠性。SOD封装作为小外形二极管的主流形态,其SOD-123、SOD-323、SOD-523三种规格分别对应不同的功耗与占板面积权衡。理解封装尺寸、焊盘设计计算逻辑和钢网开窗原理,是避免立碑、虚焊等工艺缺陷的关键。在可穿戴设备、电源保护等空间受限场景中,合理选择封装不仅能优化散热路径,还能提升量产良率。本文从焊盘计算、工艺要点到选型策略,全面解析SOD封装的工程实践。

weixin_42520780的博客 296

Android 输入事件拦截机制

doInterceptKeyBeforeDispatchingLockedInterruptible调用Java层的interceptKeyBeforeDispatching做拦截操作,然后根据返回结果设置 key event的interceptKeyResult, 如果没有拦截,设置interceptKeyResult为INTERCEPT_KEY_RESULT_CONTINUE, 否则设置为INTERCEPT_KEY_RESULT_SKIP或TRY_AGAIN.

wolf0706的专栏 1281

从NHANES到发表:如何用survey包完成符合CDC要求的统计分析(含完整R代码)

本文详细介绍了如何利用R语言的survey包,对美国国家健康与营养调查数据进行符合CDC要求的统计分析。文章重点解析了NHANES数据的复杂抽样设计、权重变量的正确选择与调整,并提供了从数据获取、清洗、构建调查设计对象到执行加权回归及生成发表级表格的完整R代码实战指南,帮助研究者避免常见错误,确保分析结果的准确性与可发表性。

weixin_29054245的博客 521

Android一文让你轻松搞定Touch事件分发

今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司19年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。还有。

2401_84132423的博客 1079

SwarmClaw:自托管多智能体AI运行时部署与实战指南

多智能体系统是人工智能领域的重要发展方向,它通过多个具备自主决策和协作能力的智能体共同完成任务,其核心原理在于分布式问题求解与协同规划。这种架构在提升任务处理效率、复杂问题分解和鲁棒性方面具有显著技术价值,广泛应用于自动化工作流、虚拟团队协作、智能客服和个性化助手等场景。本文聚焦于SwarmClaw这一自托管的多智能体AI运行时,它原生支持Model Context Protocol,并内置了超过23种AI提供商,为开发者提供了一个开箱即用且高度可定制的控制平面,便于构建和管理复杂的多智能体协作网络。

weixin_27207591的博客 401

​​手把手教你学PCIE--ATU 的 Bar 匹配模式与地址匹配模式详解​

摘要: ATU(地址转换单元)提供两种地址匹配模式:Bar匹配模式基于PCI设备的BAR寄存器自动映射虚拟地址(只需配置物理基址),适用于标准PCI设备DMA;地址匹配模式需显式配置虚拟与物理地址范围,适合自定义映射场景。核心区别在于匹配依据(BAR自动推导vs人工定义),Bar模式简化配置,地址模式更灵活。

MHD0815的博客 380

Android视图绘制和事件分发相关

Android视图绘制和事件分发相关绘制原理View重绘View绘制流程Android屏幕绘制双缓冲技术View事件分发——递归 绘制原理 Activity -包含-> PhoneWindow -继承于-> Window Activity -setContentView()-> 将View设置到PhoneWindow上 PhoneWindow -包含-> DecorView...

sst2230879的博客 370

【ComfyUI】SDXL + 单LoRA 房屋平面图渲染装修

本文介绍了一种基于ComfyUI的室内平面设计图自动生成效果图的工作流。该流程通过导入房屋平面图,结合SDXL室内设计模型与北欧风格LoRA模块,快速生成多房间效果展示。工作流包含图像输入、文本处理、模型加载和图像生成等环节,支持风格化渲染和细节补充,适用于建筑设计、家装展示、房地产营销等场景。核心采用SDXL通用室内设计模型和北欧极简LoRA,通过节点衔接实现自动化批量生成,能在短时间内将平面方案转化为逼真的三维效果图。该技术可提升设计呈现效率,辅助客户决策,并应用于教学研究领域。

Mr数据杨 3649

反思|Android 事件拦截机制的设计与实现

事件拦截机制是一个非常重要的基础知识点,而事件序列又是其中最核心的概念,无论是事件分发还是事件拦截,搞懂了事件序列的意义,其它逻辑概念的理解都不再困难。

2301_79985012的博客 1004

PCL点云库入门(第1讲)——PCL库简介和安装(Win10/11+VS2019+PCL 1.12.0)

PCL,全称为,即点云库,是一个专注于2D/3D图像和点云处理的大型开源项目。该项目最初由斯坦福大学的杰出计算机视觉专家Radu博士及其团队开发和维护,经过十余年的发展,目前(2024年12月)已更新至1.14.1版本。PCL点云库集成了众多尖端的点云处理算法,这些算法不仅包括基础的滤波、特征估计、表面重建、配准、模型拟合和分割等,还涵盖了更高级的功能,如点云数据的语义理解、场景解析以及动态环境下的实时处理。这些算法能够对含有噪声的点云数据进行有效过滤,去除异常值;

qq_36812406的博客 1万+

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

浅谈Android中的事件分发

在我们实际的项目中,涉及到手势的操作很多,这就需要我们对Android的事件有一定的了解,才能设计出好的手势。本文就对Android中的事件分发做一些简单的介绍。 1、Android中事件的基本概念 1.1、事件分发的对象 事件分发的对象就是事件,当我们触摸屏幕的时候就会触发一系列的事件。 Touch事件相关细节(发生触摸的位置、时间、历史记录、手势动作等)被封装成MotionEvent对象。 1.2、事件的种类 Android中的事件分为4类: MotionEvent.ACTION_DOWN:按下Vie

HughZhao的博客 592

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Android事件分发机制(一)

在项目中遇到过很多次的事件冲突,在博客上看过一些事件分发的文章,但是基本上都是为了先解决需求,一直没有深入的研究,没过几天就忘的差不多了,下次再遇到这方面的问题仍然需要找百度帮忙,正好这一阵有时间,想好好整理一下Android事件分发,特此记录一下。 看过很多关于事件分发的博客,写的都非常好。分享一下自己关于这块内容的学习经验,如果不清楚事件分发的流程,不太建议一上来就分析源码,可以先看 [http

dingys的专栏 380

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Android事件分发机制

事件分发流程图 1、当 UI 主线程收到触摸 input 事件,经过一系列处理,最终会走到 DecorView 的 dispatchTouchEvent 方法。 @Override public boolean dispatchTouchEvent(MotionEvent ev) { final Window.Callback cb = mWindow.getCallback(); ...

Jaqen's Blog 191

Android中的事件分发机制

1. 一个小问题引发的思考 2. 通过源码探索View中的事件分发机制 3.通过源码探索ViewGroup的事件分发机制 4.结论 5.参考文献 最近的一个项目中涉及到UGC的处理,大致布局为一个RelativeLayout包含了一个EditText和一个Button,当点击EditText时,弹出软键盘,点击RelativeLayout中除了EditText和Button之外其它的

xuzhuaaron1的博客 695

Android 事件分发 之 全家桶

你好! 确实,我今天面试,然后被问到了事件分发, 跟人家聊的稀碎,所以回来仔细查阅了点儿资料和源码,特此记录一下。就是从基础,流程,源码等多个层面进行了一个比较全面的分析,学习~

chaseDreamer_的博客 2042
上一篇: ListView的复用->购物车,listView的布局复用->聊天窗口
下一篇: 151228 侧滑菜单:Drawerlayout和ActionBar 一起使用的,侧滑菜单:SlidingPaneLayout,NavigationView,TabLayout
千雅爸爸
博客等级 码龄18年 292粉丝 639原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值