PipMenuView点击Expand按钮
对应b站免费视频教程讲解:
https://www.bilibili.com/video/BV1wj411o7A9/
hideMenu:431, PipMenuView (com.android.wm.shell.pip.phone)
expandPip:558, PipMenuView (com.android.wm.shell.pip.phone)
lambda$new$2:198, PipMenuView (com.android.wm.shell.pip.phone)
$r8$lambda$TVGiqqzKEZGnpVVCecTNWyek8VQ:-1, PipMenuView (com.android.wm.shell.pip.phone)
onClick:-1, PipMenuView$$ExternalSyntheticLambda3 (com.android.wm.shell.pip.phone)
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)
这里发现较为简单,功能就是响应一下onClick,然后启动hideMenu,会启动一个动画进行hide
核心代码如下:
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
void hideMenu(final Runnable animationFinishedRunnable, boolean notifyMenuVisibility,
boolean resize, @AnimationType int animationType) {
if (mMenuState != MENU_STATE_NONE) {
cancelDelayedHide();
if (notifyMenuVisibility) {
notifyMenuStateChangeStart(MENU_STATE_NONE, resize, null);
}
mMenuContainerAnimator = new AnimatorSet();
ObjectAnimator menuAnim = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
mMenuContainer.getAlpha(), 0f);
menuAnim.addUpdateListener(mMenuBgUpdateListener);
ObjectAnimator settingsAnim = ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA,
mSettingsButton.getAlpha(), 0f);
ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
mDismissButton.getAlpha(), 0f);
ObjectAnimator enterSplitAnim = ObjectAnimator.ofFloat(mEnterSplitButton, View.ALPHA,
mEnterSplitButton.getAlpha(), 0f);
mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim,
enterSplitAnim);
mMenuContainerAnimator.setInterpolator(Interpolators.ALPHA_OUT);
mMenuContainerAnimator.setDuration(getFadeOutDuration(animationType));
mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(GONE);
if (notifyMenuVisibility) {
notifyMenuStateChangeFinish(MENU_STATE_NONE);
}
if (animationFinishedRunnable != null) {
animationFinishedRunnable.run();
}
}
});
mMenuContainerAnimator.start();
}
}
PipMenuView动画结束后进行对应的WindowMode及bounds设置,还有对小窗的task进行动画放大动作
05-25 17:10:34.142 744 744 I test22 : WindowContainerTransaction setBounds bounds = Rect(0, 0 - 1440, 2960)
05-25 17:10:34.143 744 744 I test22 : applySyncTransaction
05-25 17:10:34.143 744 744 I test22 : java.lang.Exception
05-25 17:10:34.143 744 744 I test22 : at android.window.WindowOrganizer.applySyncTransaction(WindowOrganizer.java:81)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.common.SyncTransactionQueue$SyncCallback.send(SyncTransactionQueue.java:197)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.common.SyncTransactionQueue.queue(SyncTransactionQueue.java:80)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.PipTaskOrganizer.exitPip(PipTaskOrganizer.java:471)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PipMotionHelper.expandLeavePip(PipMotionHelper.java:364)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PipMotionHelper.expandLeavePip(PipMotionHelper.java:342)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PipTouchHandler$PipMenuListener.onPipExpand(PipTouchHandler.java:144)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PhonePipMenuController$$ExternalSyntheticLambda4.accept(Unknown Source:2)
05-25 17:10:34.143 744 744 I test22 : at java.util.ArrayList.forEach(ArrayList.java:1262)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PhonePipMenuController.onPipExpand(PhonePipMenuController.java:472)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PipMenuView$$ExternalSyntheticLambda10.run(Unknown Source:2)
05-25 17:10:34.143 744 744 I test22 : at com.android.wm.shell.pip.phone.PipMenuView$4.onAnimationEnd(PipMenuView.java:427)
05-25 17:10:34.143 744 744 I test22 : at android.animation.Animator$AnimatorListener.onAnimationEnd(Animator.java:600)
05-25 17:10:34.143 744 744 I test22 : at android.animation.AnimatorSet.endAnimation(AnimatorSet.java:1301)
05-25 17:10:34.143 744 744 I test22 : at android.animation.AnimatorSet.doAnimationFrame(AnimatorSet.java:1086)
05-25 17:10:34.143 744 744 I test22 : at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:307)
05-25 17:10:34.143 744 744 I test22 : at android.animation.AnimationHandler.-$$Nest$mdoAnimationFrame(Unknown Source:0)
05-25 17:10:34.143 744 744 I test22 : at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:86)
05-25 17:10:34.143 744 744 I test22 : at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1229)
05-25 17:10:34.143 744 744 I test22 : at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
05-25 17:10:34.143 744 744 I test22 : at android.view.Choreographer.doCallbacks(Choreographer.java:899)
05-25 17:10:34.143 744 744 I test22 : at android.view.Choreographer.doFrame(Choreographer.java:827)
05-25 17:10:34.143 744 744 I test22 : at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)
05-25 17:10:34.143 744 744 I test22 : at android.os.Handler.handleCallback(Handler.java:942)
05-25 17:10:34.143 744 744 I test22 : at android.os.Handler.dispatchMessage(Handler.java:99)
05-25 17:10:34.143 744 744 I test22 : at android.os.Looper.loopOnce(Looper.java:201)
05-25 17:10:34.143 744 744 I test22 : at android.os.Looper.loop(Looper.java:288)
05-25 17:10:34.143 744 744 I test22 : at android.app.ActivityThread.main(ActivityThread.java:7897)
05-25 17:10:34.143 744 744 I test22 : at java.lang.reflect.Method.invoke(Native Method)
05-25 17:10:34.143 744 744 I test22 : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
05-25 17:10:34.143 744 744 I test22 : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:937)
核心代码如下:
public void exitPip(int animationDurationMs, boolean requestEnterSplit) {
//省略
final Rect destinationBounds = getExitDestinationBounds();//获取目标大小,这里推出pip应该到全屏,所以destinationBounds为全屏
final int direction = syncWithSplitScreenBounds(destinationBounds, requestEnterSplit)
? TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN
: TRANSITION_DIRECTION_LEAVE_PIP;
if (Transitions.ENABLE_SHELL_TRANSITIONS && direction ==
//省略
} else {
final SurfaceControl.Transaction tx =
mSurfaceControlTransactionFactory.getTransaction();
mSurfaceTransactionHelper.scale(tx, mLeash, destinationBounds,
mPipBoundsState.getBounds());
tx.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height());
// We set to fullscreen here for now, but later it will be set to UNDEFINED for
// the proper windowing mode to take place. See #applyWindowingModeChangeOnExit.
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_FULLSCREEN); //设置windowmode为full
wct.setBounds(mToken, destinationBounds);//设置目标大小为全屏了
wct.setBoundsChangeTransaction(mToken, tx);
}
mPipTransitionState.setTransitionState(PipTransitionState.EXITING_PIP);
mSyncTransactionQueue.queue(wct);
mSyncTransactionQueue.runInSync(t -> {
final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
mPictureInPictureParams, destinationBounds);
//进行对应的pip到全屏的task窗口动画开启
final PipAnimationController.PipTransitionAnimator<?> animator =
animateResizePip(mPipBoundsState.getBounds(), destinationBounds, sourceHintRect,direction, animationDurationMs, 0 /* startingAngle */);
});
}