android T分屏 Launcher RecentsView部分介绍/android framework手机车机系统开发

1 桌面部分第一阶段动画:

b站免费视频教程讲解:
https://www.bilibili.com/video/BV1wj411o7A9/
在这里插入图片描述
桌面点击这个Split top按钮的onClick后触发自己进程的view相关的动画:
在这里插入图片描述

点击之后会有相关动画的准备工作:
点击后会动画进入如下图一样状态,这个短信app放到上面,下面多任务依旧是多任务,位置确实变化了
在这里插入图片描述

相关动画调用栈:

createTaskDismissAnimation:2975, RecentsView (com.android.quickstep.views)
createSplitSelectInitAnimation:4022, RecentsView (com.android.quickstep.views)
handleSplitSelectionState:120, RecentsViewStateController (com.android.launcher3.uioverrides)
setStateWithAnimationInternal:96, RecentsViewStateController (com.android.launcher3.uioverrides)
setStateWithAnimation:87, BaseRecentsViewStateController (com.android.launcher3.uioverrides)
setStateWithAnimation:53, BaseRecentsViewStateController (com.android.launcher3.uioverrides)
createAnimationToNewWorkspaceInternal:324, StateManager (com.android.launcher3.statemanager)
goToStateAnimated:259, StateManager (com.android.launcher3.statemanager)
goToState:247, StateManager (com.android.launcher3.statemanager)
goToState:150, StateManager (com.android.launcher3.statemanager)
goToState:143, StateManager (com.android.launcher3.statemanager)
initiateSplitSelect:182, LauncherRecentsView (com.android.quickstep.views)
initiateSplitSelect:1541, TaskView (com.android.quickstep.views)
onClick:132, TaskShortcutFactory$SplitSelectSystemShortcut (com.android.quickstep)
lambda$addMenuOption$1:254, TaskMenuView (com.android.quickstep.views)
run:-1, TaskMenuView$$ExternalSyntheticLambda2 (com.android.quickstep.views)
finishRecentsAnimation:4535, RecentsView (com.android.quickstep.views)
lambda$addMenuOption$2:252, TaskMenuView (com.android.quickstep.views)
run:-1, TaskMenuView$$ExternalSyntheticLambda1 (com.android.quickstep.views)
switchToScreenshot:4961, RecentsView (com.android.quickstep.views)
lambda$addMenuOption$3$com-android-quickstep-views-TaskMenuView:251, TaskMenuView (com.android.quickstep.views)
onClick:-1, TaskMenuView$$ExternalSyntheticLambda5 (com.android.quickstep.views)
performClick:7506, View (android.view)
performClickInternal:7483, View (android.view)
-$$Nest$mperformClickInternal:-1, View (android.view)
run:29335, View$PerformClick (android.view)
handleCallback:942, Handler (android.os)
dispatchMessage:99, Handler (android.os)
loopOnce:201, Looper (android.os)
loop:288, Looper (android.os)
main:7897, ActivityThread (android.app)
invoke:-1, Method (java.lang.reflect)
run:548, RuntimeInit$MethodAndArgsCaller (com.android.internal.os)
main:937, ZygoteInit (com.android.internal.os)

因为代码太多,只对上半部分的TaskView动画进行相关的说明:
这里createTaskDismissAnimation其实就是上面那个短信应用上半屏幕部分显示的动画构建

/**
     * Places an {@link FloatingTaskView} on top of the thumbnail for {@link #mSplitHiddenTaskView}
     * and then animates it into the split position that was desired
     */
    private void createInitialSplitSelectAnimation(PendingAnimation anim) {
    
    
        mOrientationHandler.getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
                mSplitPlaceholderInset, mActivity.getDeviceProfile(),
                mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);

        RectF startingTaskRect = new RectF();
        if (mSplitHiddenTaskView != null) {
    
    
            mSplitHiddenTaskView.setVisibility(INVISIBLE);//把TaskView设置不可见
            //要创建一个TaskView的副本,并且要把这个副本进行相关的动画播放显示在最顶端一个小区域
            mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
                    mSplitHiddenTaskView.getThumbnail(),
                    mSplitHiddenTaskView.getThumbnail().getThumbnail(),
                    mSplitHiddenTaskView.getIconView().getDrawable(), startingTaskRect);
            mFirstFloatingTaskView.setAlpha(1);
            //根据相关的初始化尺寸来构建对应anim
            mFirstFloatingTaskView.addAnimation(anim, startingTaskRect, mTempRect,
                    true /* fadeWithThumbnail */, true /* isStagedTask */);
        } else {
    
    
         
        }
        anim.addEndListener(success -> {
    
    
            if (success) {
    
    
                mSplitToast.show();
                //动画播放完成后,显示出一个Toast "Tap another app to use split-screen"
            }
        });
    }

其他TaskView动画就不进行相关的介绍了,都在这调用堆栈里面,到此时分屏在桌面多任务完成了第一步,把TaskView放到顶部(上屏),接下来要等待用户来手动选择一个下屏app,才可以构成真正意义的分屏。
在这里插入图片描述

2 桌面选择点击底部TaskView点击,及相关动画启动

底部点击TaskView触发动画流程相对比较简单:

 private void onClick(View view) {
    
    
        if (confirmSecondSplitSelectApp()) {
    
    
            return;
        }
}
 private boolean confirmSecondSplitSelectApp() {
    
    
        int index = getChildTaskIndexAtPosition(mLastTouchDownPosition);
        TaskIdAttributeContainer container = mTaskIdAttributeContainer[index];
        //调用到了RecentsView的confirmSplitSelect方法
        return getRecentsView().confirmSplitSelect(this, container.getTask(),
                container.getIconView(), container.getThumbnailView());
    }

	//方法进行相关的动画准备和启动
     public boolean confirmSplitSelect(TaskView containerTaskView, Task task, IconView iconView,
            TaskThumbnailView thumbnailView) {
    
    
        //省略
        mSplitSelectStateController.setSecondTask(task);//设置底部区域要显示的task
        RectF secondTaskStartingBounds = new RectF();//初始化底部的区域
        Rect secondTaskEndingBounds = new Rect();
        Rect firstTaskStartingBounds = new Rect();//初始化顶部的区域
        Rect firstTaskEndingBounds = mTempRect;
        //获取动画时间
        int duration = mActivity.getStateManager().getState().getTransitionDuration(mActivity,
                false /* isToState */);
        PendingAnimation pendingAnimation = new PendingAnimation(duration);

        int halfDividerSize = getResources()
                .getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
                //获取对应的一个上屏幕区域和下屏幕区域截至区域firstTaskEndingBounds,secondTaskEndingBounds
        mOrientationHandler.getFinalSplitPlaceholderBounds(halfDividerSize,
                mActivity.getDeviceProfile(),
                mSplitSelectStateController.getActiveSplitStagePosition(), firstTaskEndingBounds,
                secondTaskEndingBounds);
		
		//获取当前的上屏幕区域坐标情况放入firstTaskStartingBounds
        mFirstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds);
        //有了初始区域和结束区域,进行相关的动画配置
        mFirstFloatingTaskView.addAnimation(pendingAnimation,
                new RectF(firstTaskStartingBounds), firstTaskEndingBounds,
                false /* fadeWithThumbnail */, true /* isStagedTask */);

//下屏部分和商品部分类是不再讲解
        mSecondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
                thumbnailView, thumbnailView.getThumbnail(),
                iconView.getDrawable(), secondTaskStartingBounds);
        mSecondFloatingTaskView.setAlpha(1);
        mSecondFloatingTaskView.addAnimation(pendingAnimation, secondTaskStartingBounds,
                secondTaskEndingBounds, true /* fadeWithThumbnail */, false /* isStagedTask */);
          //进行动画结束监听,在动画结束时候才进行launchSplitTasks,即正式调用到systemui和systemserver让赶紧启动真正分屏
        pendingAnimation.addEndListener(aBoolean -> {
    
    
            mSplitSelectStateController.launchSplitTasks(
                    aBoolean1 -> RecentsView.this.resetFromSplitSelectionState());
        });
        if (containerTaskView.containsMultipleTasks()) {
    
    
            // If we are launching from a child task, then only hide the thumbnail itself
            mSecondSplitHiddenView = thumbnailView;
        } else {
    
    
            mSecondSplitHiddenView = containerTaskView;
        }
        mSecondSplitHiddenView.setVisibility(INVISIBLE);//下屏的TaskView要被隐藏
        pendingAnimation.buildAnim().start();//启动正式动画
        return true;
    }

正式调用systemui相关的shell接口进行操作真正的task相关分屏业务:

launchTasks:201, SplitSelectStateController (com.android.quickstep.util)
launchSplitTasks:124, SplitSelectStateController (com.android.quickstep.util)
lambda$confirmSplitSelect$24$com-android-quickstep-views-RecentsView:4081, RecentsView (com.android.quickstep.views)
accept:-1, RecentsView$$ExternalSyntheticLambda30 (com.android.quickstep.views)
onAnimationEnd:80, AnimatorListeners$EndStateCallbackWrapper (com.android.launcher3.anim)
:-1, Animator$AnimatorListener (android.animation)
endAnimation:1333, ValueAnimator (android.animation)
doAnimationFrame:1575, ValueAnimator (android.animation)
pulseAnimationFrame:1591, ValueAnimator (android.animation)
pulseFrame:1170, AnimatorSet (android.animation)
handleAnimationEvents:1153, AnimatorSet (android.animation)
doAnimationFrame:1053, AnimatorSet (android.animation)
doAnimationFrame:307, AnimationHandler (android.animation)
-$$Nest$mdoAnimationFrame:-1, AnimationHandler (android.animation)
doFrame:86, AnimationHandler$1 (android.animation)
run:1229, Choreographer$CallbackRecord (android.view)
run:1239, Choreographer$CallbackRecord (android.view)
doCallbacks:899, Choreographer (android.view)
doFrame:827, Choreographer (android.view)
run:1214, Choreographer$FrameDisplayEventReceiver (android.view)
handleCallback:942, Handler (android.os)
dispatchMessage:99, Handler (android.os)
loopOnce:201, Looper (android.os)
loop:288, Looper (android.os)
main:7897, ActivityThread (android.app)
invoke:-1, Method (java.lang.reflect)
run:548, RuntimeInit$MethodAndArgsCaller (com.android.internal.os)
main:937, ZygoteInit (com.android.internal.os)

猜你喜欢

转载自blog.csdn.net/learnframework/article/details/130901312