3分钟伪代码解释android事件分发

2分钟把握核心

到一些解释android事件分发的,基本都是穷举一些所有情况整几个大图,名词概念搬一搬,也不说为什么会这样,很长,实战或面试的时候能拿来用吗?本人不才,认为以下的伪代码基本能搞定事件分发,自己自定义view的时候也可以直接跟着用,父与子往下传递,你从Activity到DecorView开始分析,实战岂不是得从盘古开天开始讲起吗?我们源码直接干,下面是简化源码

if (!禁止打断()&& 是否打断()) {
 viewgroup可以要了
} else {
 	for (int i = 0; i < childs.size(); i++) {
	if (somechild.//即somechild.onTouchEvent) {
     return true;
	}
 }
}
        
return    viewgroup可以要了

父想要咋办

方案1: 使"!禁止打断()&& 是否打断()" 为true
方案2: child.要全为false

子想要咋办

方案3: 禁止打断为true
方案4: 要的那个view的child.要为true

完事 so easy 如果还没有概括不了情况 欢迎指正

一般如果你理解了上面,事件分发基本你已经悟到了
如今开发10年过去 上述里面就没有做不了的自定义view,可以运用各种复杂的事件

到此下课!下面可以不看,直接去对抗面试官

1分钟看懂案例

说了半天打断?是谁打断 是父布局 onInterceptTouchEvent

1. 方案1场景举例使用

 NoScrollViewPager

2. 方案2场景举例使用
自然场景 父布局自行消费

3. 方案3场景举例使用
产品让你在竖着滑动的ScrollView/RV,上面加个横滑的banner,你突然发现横滑有点子卡,本来是子不要父才有。但父先具备的滑动能力,他选择了打断,但此时子又不能完全抢占,竖滑是必须,所以判断滑动方向,且在新
加的banner时候,使用下面方法 动态抢占和释放

parent.requestDisallowInterceptTouchEvent(disallowIntercept)

4. 方案4场景举例使用
父布局是item有自己的点击事件 跳A页面,但这里面有个头像又跳B 详情,此时给双方都加上点击事件即可,子自己优先消费了,不会冲突,你也许会问,两个人都在抢点击,父布局的其他部分怎么就不冲突了呢
TouchEvent的前提是判断的x,y 你都不在一个地方冲突个鸡儿,方案3 banner之外的滑动他又影响不了

再次下课!下面可以不看,直接去自定义任何高级view

以下为伪代码可以不看

public class IView {

    public  boolean dispatchTouchEvent() {
        return onTouchEvent();
    }

    public  boolean onTouchEvent() {
        //可以通过setOnTouchListener等消费则  return true
        return false;
    }
}
public class IViewGroup extends IView {
    public List<IView> childs = new ArrayList<>();//

    //注释1:理解事件分发有个容易被忽视的前提就是ViewGroup是继承的View
    //虽然ViewGroup没有实现onTouchEvent 但是super.dispatchTouchEvent调用的就是super.onTouchEvent 即他自己的onTouchEvent
    public boolean onInterceptTouchEvent() {
        return false;//
    }

    @Override
    public boolean dispatchTouchEvent() {
        if (true) {
            //这个true就是
            //  final int action = ev.getAction();
            // final int actionMasked = action & MotionEvent.ACTION_MASK;
            // actionMasked == MotionEvent.ACTION_DOWN
            resetTouchState();//FLAG_DISALLOW_INTERCEPT==false
            //这里的意思就是findid后 直接调requestDisallowInterceptTouchEvent没有暖用
            //此处被重置 为false需要在这个if后面调
        }

        if (!FLAG_DISALLOW_INTERCEPT && onInterceptTouchEvent()) { //只有FLAG_DISALLOW_INTERCEPT为false才去判断onInterceptTouchEvent
            super.dispatchTouchEvent();//注释1
        } else {
            for (int i = 0; i < childs.size(); i++) {
                if (childs.get(i).dispatchTouchEvent()) {
                    return true;//只有一个child View的dispatchTouchEvent(注释1)返回true
                    //那么后续的view也拿不到 super(他自己)也拿不到
                }
            }
        }
        return super.dispatchTouchEvent();
    }

    private boolean FLAG_DISALLOW_INTERCEPT = false; //是否禁止打断

    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
        FLAG_DISALLOW_INTERCEPT = disallowIntercept;
        //如果viewgroup有父就 parent.requestDisallowInterceptTouchEvent(disallowIntercept)
    }

    public void resetTouchState() {
        FLAG_DISALLOW_INTERCEPT = false;
    }
}

如果你还想考虑到down move up 伪代码二次优化。
View mTarget=null;//保存捕获Touch事件处理的View
    public boolean dispatchTouchEvent(MotionEvent ev) {

        //....其他处理,在此不管
        
        if(ev.getAction()==KeyEvent.ACTION_DOWN){
            //每次Down事件,都置为Null

            if(FLAG_DISALLOW_INTERCEPT ||!onInterceptTouchEvent()){
            mTarget=null;
            View[] views=getChildView();
            for(int i=0;i<views.length;i++){
                if(views[i].dispatchTouchEvent(ev))
                    mTarget=views[i];
                    return true;
            }
          }
        }
        //当子View没有捕获down事件时,ViewGroup自身处理。这里处理的Touch事件包含Down、Up和Move
        if(mTarget==null){
            return super.dispatchTouchEvent(ev);
        }
        //...其他处理,在此不管
        if(onInterceptTouchEvent()){
         //...其他处理,在此不管    
         }
//这一步在Action_Down中是不会执行到的,只有Move和UP才会执行到。
        return mTarget.dispatchTouchEvent(ev);

    }
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值