• launcher功能入口(三)


    背景描述

    本篇文章补充一下之前https://blog.csdn.net/a396604593/article/details/123487805文章中的一些没填上的坑。
    此代码基于Android 12

    上篇:Launcher功能入口
    上篇:launcher功能入口(二)
    本篇:launcher功能入口(三)

    Launcher滑动分析

    10、上滑进入recent
    packages\apps\Launcher3\quickstep\src\com\android\launcher3\uioverrides\touchcontrollers\NoButtonNavbarToOverviewTouchController.java

    public void onDragStart(boolean start, float startDisplacement) {
    		if (handlingOverviewAnim()) {//判断是否拦截
    			//设置停顿监听
                mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseDetected);
            }
    }
    	//mDidTouchStartInNavBar赋值
        @Override
        protected boolean canInterceptTouch(MotionEvent ev) {
            mDidTouchStartInNavBar = (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0;
            return super.canInterceptTouch(ev);
        }
        //判断时在底部上滑,并且在主界面
        private boolean handlingOverviewAnim() {
            int stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
            return mDidTouchStartInNavBar && mStartState == NORMAL
                    && (stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0;
        }
    //运动暂停检测,recent的触发是底部上滑并且停顿了一下,就会进入recent界面(Android 12,之前版本的recent触发有所不同)
    mMotionPauseDetector.addPosition(event);
    //取消mCurrentAnimation动画,进入recent
    private void onMotionPauseDetected() {
            if (mCurrentAnimation == null) {
                return;
            }
            mNormalToHintOverviewScrimAnimator = null;
            mCurrentAnimation.getTarget().addListener(newCancelListener(() ->
                    mLauncher.getStateManager().goToState(OVERVIEW, true, forSuccessCallback(() -> {
                        mOverviewResistYAnim = AnimatorControllerWithResistance
                                .createRecentsResistanceFromOverviewAnim(mLauncher, null)
                                .createPlaybackController();
                        mReachedOverview = true;
                        maybeSwipeInteractionToOverviewComplete();
                    }))));
    
            mCurrentAnimation.getTarget().removeListener(mClearStateOnCancelListener);
            mCurrentAnimation.dispatchOnCancel();
            mStartedOverview = true;
            VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    12、上滑进入all apps
    1、packages\apps\Launcher3\src\com\android\launcher3\touch\BaseSwipeDetector.java
    处理触摸滚动事件

    public boolean onTouchEvent(MotionEvent ev) {...}
    
    • 1

    2、packages\apps\Launcher3\src\com\android\launcher3\touch\AbstractStateChangeTouchController.java
    中判断滑动距离或者速度,决定进入或者不进入allapps

    public void onDragEnd(float velocity) {
    ...
    		if (fling) {
                targetState =
                        Float.compare(Math.signum(velocity), Math.signum(mProgressMultiplier)) == 0
                                ? mToState : mFromState;
                // snap to top or bottom using the release velocity
            } else {
                targetState =
                        (interpolatedProgress > SUCCESS_TRANSITION_PROGRESS) ? mToState : mFromState;
            }
    ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注意:mCurrentAnimation动画负责进入退出all apps
    没有直接调用packages\apps\Launcher3\src\com\android\launcher3\statemanager\StateManager.java中的goToState方法。

    12.1、上滑进入应用列表界面透明度变化

    packages/apps/Launcher3/src/com/android/launcher3/allapps/AllAppsTransitionController.java
    setAlphas中处理
    
    • 1
    • 2

    12.2、快速滑动进入退出allapps界面速度分析
    packages/apps/Launcher3/src/com/android/launcher3/touch/SwipeDetector.java

    private void reportDragEnd() {
        mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);//速度计算,计算一秒滑过多少像素
        float velocity = mDir.getVelocity(mVelocityTracker, mIsRtl) / 1000;//一秒钟滑动过多少k像素
        if (DBG) {
            Log.d(TAG, String.format("onScrollEnd disp=%.1f, velocity=%.1f",
                    mDisplacement, velocity));
        }
        //
        mListener.onDragEnd(velocity, Math.abs(velocity) > RELEASE_VELOCITY_PX_MS);//传入速度和速递阈值判断,速度大于1k 才认为是fling
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    packages/apps/Launcher3/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java

    onDragEnd根据参数判断是否是fling 如果是 则进入或者退出allapps, 如果不是 判断动画距离是否过半,如果超过0.5f 则改变状态,否则回到上一个状态

    13、桌面下拉显示通知栏
    packages\apps\Launcher3\quickstep\src\com\android\launcher3\uioverrides\touchcontrollers\StatusBarTouchController.java
    StatusBarTouchController拦截滑动事件并传递给systemui

    //事件拦截
    private boolean canInterceptTouch(MotionEvent ev) {...}
    //事件分发
    private void dispatchTouchEvent(MotionEvent ev) {
            if (mSystemUiProxy.isActive()) {
                mLastAction = ev.getActionMasked();
                mSystemUiProxy.onStatusBarMotionEvent(ev);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    触摸事件流程总结

    1、触摸事件的根是从packages\apps\Launcher3\src\com\android\launcher3\dragndrop\DragLayer.java分发下来。
    packages\apps\Launcher3\src\com\android\launcher3\views\BaseDragLayer.java中找到处理事件对应的controller
    然后由具体的controller处理滑动事件。

    private TouchController findControllerToHandleTouch(MotionEvent ev) {
            AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
            if (topView != null
                    && (isEventInLauncher(ev) || topView.canInterceptEventsInSystemGestureRegion())
                    && topView.onControllerInterceptTouchEvent(ev)) {
                return topView;
            }
    
            for (TouchController controller : mControllers) {
                if (controller.onControllerInterceptTouchEvent(ev)) {
                    Log.d("TouchController","TouchController: "+controller);
                    return controller;
                }
            }
            return null;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2、TouchController 接口,主要关注onControllerTouchEvent和onControllerInterceptTouchEvent方法。
    触摸事件都在TouchController的实现类中进行。比较多,这里就不贴出来了

    public interface TouchController {
        /**
         * Called when the draglayer receives touch event.
         */
        boolean onControllerTouchEvent(MotionEvent ev);
        /**
         * Called when the draglayer receives a intercept touch event.
         */
        boolean onControllerInterceptTouchEvent(MotionEvent ev);
        /**
         * Called when one handed mode state changed
         */
        default void onOneHandedModeStateChanged(boolean activated) { }
        default void dump(String prefix, PrintWriter writer) { }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3、launcher中滑动处理比较多,有时候找不到对应的处理逻辑。
    要忽略复杂多变的实现类,从事件传递根或者重要接口出发,判断是哪个实现类拦截处理了触摸事件。
    然后再找具体的拦截判断和触摸事件处理逻辑

    implements TouchController, SingleAxisSwipeDetector.Listener
    
    • 1
    InputConsumer输入事件

    https://blog.csdn.net/a396604593/article/details/123487805中
    11、三方应用界面上滑返回launcher
    简单写了一下三方应用界面上滑launcher怎么处理输入事件。
    跟踪此类问题和触摸事件类似,实现类比较多,要多关注接口。有一个整体的逻辑之后再看具体的处理

    也可以看一下其它人写的https://blog.csdn.net/tq501501/article/details/120002676还不错。

    16、主屏幕设置–通知圆点

    有时候通知圆点显示三角形,没有默认赋予权限。
    配置config_defaultListenerAccessPackages即可,framework下面的不生效需要查一下是否gms包覆盖掉了:
    vendor/partner_gms/overlay/GmsConfigOverlayCommon/res/values/config.xml

        <!-- Colon separated list of package names that should be granted Notification Listener access -->
        <string name="config_defaultListenerAccessPackages" translatable="false">com.android.launcher3:com.google.android.projection.gearhead</string>
    
    • 1
    • 2

    临时验证:

    adb shell  settings put secure enabled_notification_listeners com.google.android.projection.gearhead/com.google.android.gearhead.notifications.SharedNotificationListenerManager$ListenerService:com.android.launcher3/com.android.launcher3.notification.NotificationListener
    
    • 1

    之前写过一点流程,忘记了,这里加一个跳转链接https://blog.csdn.net/a396604593/article/details/128025161

    17 、widget大小调整框

    AppWidgetResizeFrame.showForWidget
    
    • 1
  • 相关阅读:
    用c动态数组(不用c++vector)实现手撸神经网咯230901
    电脑网络很卡问题排查
    Delphi 的操作符重载 - Record 结构体
    Python基础(七)之数值类型集合
    win10系统错误:Mineud.exe-系统措误 ,无法启动此程序,因为计算机中丢失iUtils.dll。尝试重新安装该程序以解决此问题。
    Node-怎么连接MySQL
    Kubernetes安装GitLab
    Spring MVC 和 @ModelAttribute 注释
    下载量突破10亿,MinIO的开源启示录
    二叉搜索树
  • 原文地址:https://blog.csdn.net/a396604593/article/details/127965396