Android View系统源码分析(二)—— ViewRoot.deliverPointerEvent()

ViewRoot.deliverPointerEvent()的具体过程


    private void deliverPointerEvent(MotionEvent event) {
        if (mTranslator != null) {
 
        //1. 进行物理像素到逻辑像素的转换,在一般情况下,物理屏幕的像素等于操作系统中定义的屏幕像素,不需要转换,只有当两者不同时才需要转换。
 
            mTranslator.translateEventInScreenToAppWindow(event);
        }
 
        boolean handled;
        if (mView != null && mAdded) {
 
            // enter touch mode on the down
            boolean isDown = event.getAction() == MotionEvent.ACTION_DOWN;
            if (isDown) {
 
        //2. 如果是DOWN消息,调用 ensureTouchMode(true)函数则进入触摸模式,与之相反的是"非触摸模式",即按键模式。该函数会引起相关的View状态的变化。
 
                ensureTouchMode(true);                              
            }
            if(Config.LOGV) {
                captureMotionLog("captureDispatchPointer", event);
            }
            if (mCurScrollY != 0) {
 
        //3. 将屏幕坐标转换到视图坐标。触摸消息本身的坐标位置是相对于屏幕左上角,而View可以认为是没有边界的,它内部处理消息时所需要的坐标是相对于View本身的。
                    //1. 转换方法很简单,变量mCurScollY记录了该View在屏幕坐标中的Y轴滚动,对于ViewRoot而言,没有X轴的滚动,因为ViewRoot的宽度已经被设置为屏幕本身的宽度。       
 
                event.offsetLocation(0, mCurScrollY);
            }
            if (MEASURE_LATENCY) {
                lt.sample("A Dispatching TouchEvents", System.nanoTime() - event.getEventTimeNano());
            }
 
        //4. 调用mView.dispatchTouchEvent()将消息派发给根View,该函数内部会继续将消息派发到整个View树。 
            //  1. 对于Activity包含的窗口,根View就是 PhoneWindow 中的 DecorView 。   
            //  2. 对于非应用窗口,根View只是一个普通的ViewGroup。
 
            handled = mView.dispatchTouchEvent(event);
 
            if (MEASURE_LATENCY) {
                lt.sample("B Dispatched TouchEvents ", System.nanoTime() - event.getEventTimeNano());
            }
            if (!handled && isDown) {
 
        //5. 如果根View及其所有的子View都没有消耗该消息,最后处理屏幕边界偏移。作用是当用户正好触摸到屏幕的边界时,系统自动对原始消息进行一定的偏移,然后在新的偏移后的位置上寻找是否有匹配的View,如果有则将消息派发到该View。
 
                int edgeSlop = mViewConfiguration.getScaledEdgeSlop();
 
                final int edgeFlags = event.getEdgeFlags();
                int direction = View.FOCUS_UP;
                int x = (int)event.getX();
                int y = (int)event.getY();
                final int[] deltas = new int[2];
 
                if ((edgeFlags & MotionEvent.EDGE_TOP) != 0) {
                    direction = View.FOCUS_DOWN;
                    if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
                        deltas[0] = edgeSlop;
                        x += edgeSlop;
                    } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
                        deltas[0] = -edgeSlop;
                        x -= edgeSlop;
                    }
                } else if ((edgeFlags & MotionEvent.EDGE_BOTTOM) != 0) {
                    direction = View.FOCUS_UP;
                    if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
                        deltas[0] = edgeSlop;
                        x += edgeSlop;
                    } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
                        deltas[0] = -edgeSlop;
                        x -= edgeSlop;
                    }
                } else if ((edgeFlags & MotionEvent.EDGE_LEFT) != 0) {
                    direction = View.FOCUS_RIGHT;
                } else if ((edgeFlags & MotionEvent.EDGE_RIGHT) != 0) {
                    direction = View.FOCUS_LEFT;
                }
 
                if (edgeFlags != 0 && mView instanceof ViewGroup) {
                    View nearest = FocusFinder.getInstance().findNearestTouchable(
                            ((ViewGroup) mView), x, y, direction, deltas);
                    if (nearest != null) {
                        event.offsetLocation(deltas[0], deltas[1]);
                        event.setEdgeFlags(0);
                        mView.dispatchTouchEvent(event);
                    }
                }
            }
        }
    }
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值