Merge "Refactor/Clean up on PiP dismiss code."

This commit is contained in:
Ben Lin
2020-10-06 00:51:35 +00:00
committed by Android (Google) Code Review
5 changed files with 312 additions and 305 deletions

View File

@@ -0,0 +1,295 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wm.shell.pip.phone;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.TransitionDrawable;
import android.os.Handler;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringForce;
import com.android.wm.shell.R;
import com.android.wm.shell.animation.PhysicsAnimator;
import com.android.wm.shell.common.DismissCircleView;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
import com.android.wm.shell.pip.PipUiEventLogger;
import kotlin.Unit;
/**
* Handler of all Magnetized Object related code for PiP.
*/
public class PipDismissTargetHandler {
/* The multiplier to apply scale the target size by when applying the magnetic field radius */
private static final float MAGNETIC_FIELD_RADIUS_MULTIPLIER = 1.25f;
/** Duration of the dismiss scrim fading in/out. */
private static final int DISMISS_TRANSITION_DURATION_MS = 200;
/**
* MagnetizedObject wrapper for PIP. This allows the magnetic target library to locate and move
* PIP.
*/
private final MagnetizedObject<Rect> mMagnetizedPip;
/**
* Container for the dismiss circle, so that it can be animated within the container via
* translation rather than within the WindowManager via slow layout animations.
*/
private final ViewGroup mTargetViewContainer;
/** Circle view used to render the dismiss target. */
private final DismissCircleView mTargetView;
/**
* MagneticTarget instance wrapping the target view and allowing us to set its magnetic radius.
*/
private final MagnetizedObject.MagneticTarget mMagneticTarget;
/** PhysicsAnimator instance for animating the dismiss target in/out. */
private final PhysicsAnimator<View> mMagneticTargetAnimator;
/** Default configuration to use for springing the dismiss target in/out. */
private final PhysicsAnimator.SpringConfig mTargetSpringConfig =
new PhysicsAnimator.SpringConfig(
SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
/**
* Runnable that can be posted delayed to show the target. This needs to be saved as a member
* variable so we can pass it to removeCallbacks.
*/
private Runnable mShowTargetAction = this::showDismissTargetMaybe;
// Allow dragging the PIP to a location to close it
private final boolean mEnableDismissDragToEdge;
private int mDismissAreaHeight;
private final Context mContext;
private final PipMotionHelper mMotionHelper;
private final PipUiEventLogger mPipUiEventLogger;
private final WindowManager mWindowManager;
private final Handler mHandler;
public PipDismissTargetHandler(Context context, PipUiEventLogger pipUiEventLogger,
PipMotionHelper motionHelper, Handler handler) {
mContext = context;
mPipUiEventLogger = pipUiEventLogger;
mMotionHelper = motionHelper;
mHandler = handler;
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Resources res = context.getResources();
mEnableDismissDragToEdge = res.getBoolean(R.bool.config_pipEnableDismissDragToEdge);
mDismissAreaHeight = res.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height);
mTargetView = new DismissCircleView(context);
mTargetViewContainer = new FrameLayout(context);
mTargetViewContainer.setBackgroundDrawable(
context.getDrawable(R.drawable.floating_dismiss_gradient_transition));
mTargetViewContainer.setClipChildren(false);
mTargetViewContainer.addView(mTargetView);
mMagnetizedPip = mMotionHelper.getMagnetizedPip();
mMagneticTarget = mMagnetizedPip.addTarget(mTargetView, 0);
updateMagneticTargetSize();
mMagnetizedPip.setAnimateStuckToTarget(
(target, velX, velY, flung, after) -> {
if (mEnableDismissDragToEdge) {
mMotionHelper.animateIntoDismissTarget(target, velX, velY, flung, after);
}
return Unit.INSTANCE;
});
mMagnetizedPip.setMagnetListener(new MagnetizedObject.MagnetListener() {
@Override
public void onStuckToTarget(@NonNull MagnetizedObject.MagneticTarget target) {
// Show the dismiss target, in case the initial touch event occurred within the
// magnetic field radius.
if (mEnableDismissDragToEdge) {
showDismissTargetMaybe();
}
}
@Override
public void onUnstuckFromTarget(@NonNull MagnetizedObject.MagneticTarget target,
float velX, float velY, boolean wasFlungOut) {
if (wasFlungOut) {
mMotionHelper.flingToSnapTarget(velX, velY, null /* endAction */);
hideDismissTargetMaybe();
} else {
mMotionHelper.setSpringingToTouch(true);
}
}
@Override
public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) {
mMotionHelper.notifyDismissalPending();
handler.post(() -> {
mMotionHelper.animateDismiss();
hideDismissTargetMaybe();
});
mPipUiEventLogger.log(
PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_DRAG_TO_REMOVE);
}
});
mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView);
}
/**
* Potentially start consuming future motion events if PiP is currently near the magnetized
* object.
*/
public boolean maybeConsumeMotionEvent(MotionEvent ev) {
return mMagnetizedPip.maybeConsumeMotionEvent(ev);
}
/**
* Update the magnet size.
*/
public void updateMagneticTargetSize() {
if (mTargetView == null) {
return;
}
final Resources res = mContext.getResources();
final int targetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size);
mDismissAreaHeight = res.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height);
final FrameLayout.LayoutParams newParams =
new FrameLayout.LayoutParams(targetSize, targetSize);
newParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
newParams.bottomMargin = mContext.getResources().getDimensionPixelSize(
R.dimen.floating_dismiss_bottom_margin);
mTargetView.setLayoutParams(newParams);
// Set the magnetic field radius equal to the target size from the center of the target
mMagneticTarget.setMagneticFieldRadiusPx(
(int) (targetSize * MAGNETIC_FIELD_RADIUS_MULTIPLIER));
}
/** Adds the magnetic target view to the WindowManager so it's ready to be animated in. */
public void createOrUpdateDismissTarget() {
if (!mTargetViewContainer.isAttachedToWindow()) {
mHandler.removeCallbacks(mShowTargetAction);
mMagneticTargetAnimator.cancel();
mTargetViewContainer.setVisibility(View.INVISIBLE);
try {
mWindowManager.addView(mTargetViewContainer, getDismissTargetLayoutParams());
} catch (IllegalStateException e) {
// This shouldn't happen, but if the target is already added, just update its layout
// params.
mWindowManager.updateViewLayout(
mTargetViewContainer, getDismissTargetLayoutParams());
}
} else {
mWindowManager.updateViewLayout(mTargetViewContainer, getDismissTargetLayoutParams());
}
}
/** Returns layout params for the dismiss target, using the latest display metrics. */
private WindowManager.LayoutParams getDismissTargetLayoutParams() {
final Point windowSize = new Point();
mWindowManager.getDefaultDisplay().getRealSize(windowSize);
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
mDismissAreaHeight,
0, windowSize.y - mDismissAreaHeight,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
lp.setTitle("pip-dismiss-overlay");
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.setFitInsetsTypes(0 /* types */);
return lp;
}
/** Makes the dismiss target visible and animates it in, if it isn't already visible. */
public void showDismissTargetMaybe() {
if (!mEnableDismissDragToEdge) {
return;
}
createOrUpdateDismissTarget();
if (mTargetViewContainer.getVisibility() != View.VISIBLE) {
mTargetView.setTranslationY(mTargetViewContainer.getHeight());
mTargetViewContainer.setVisibility(View.VISIBLE);
// Cancel in case we were in the middle of animating it out.
mMagneticTargetAnimator.cancel();
mMagneticTargetAnimator
.spring(DynamicAnimation.TRANSLATION_Y, 0f, mTargetSpringConfig)
.start();
((TransitionDrawable) mTargetViewContainer.getBackground()).startTransition(
DISMISS_TRANSITION_DURATION_MS);
}
}
/** Animates the magnetic dismiss target out and then sets it to GONE. */
public void hideDismissTargetMaybe() {
if (!mEnableDismissDragToEdge) {
return;
}
mHandler.removeCallbacks(mShowTargetAction);
mMagneticTargetAnimator
.spring(DynamicAnimation.TRANSLATION_Y,
mTargetViewContainer.getHeight(),
mTargetSpringConfig)
.withEndActions(() -> mTargetViewContainer.setVisibility(View.GONE))
.start();
((TransitionDrawable) mTargetViewContainer.getBackground()).reverseTransition(
DISMISS_TRANSITION_DURATION_MS);
}
/**
* Removes the dismiss target and cancels any pending callbacks to show it.
*/
public void cleanUpDismissTarget() {
mHandler.removeCallbacks(mShowTargetAction);
if (mTargetViewContainer.isAttachedToWindow()) {
mWindowManager.removeViewImmediate(mTargetViewContainer);
}
}
}

View File

@@ -155,20 +155,6 @@ public class PipMenuActivityController {
}
}
/**
* Updates the appearance of the menu and scrim on top of the PiP while dismissing.
*/
public void setDismissFraction(float fraction) {
final boolean isMenuVisible = isMenuVisible();
if (DEBUG) {
Log.d(TAG, "setDismissFraction() isMenuVisible=" + isMenuVisible
+ " fraction=" + fraction);
}
if (isMenuVisible) {
mPipMenuView.updateDismissFraction(fraction);
}
}
/**
* Similar to {@link #showMenu(int, Rect, boolean, boolean, boolean)} but only show the menu
* upon PiP window transition is finished.

View File

@@ -429,25 +429,6 @@ public class PipMenuView extends FrameLayout {
}
}
void updateDismissFraction(float fraction) {
int alpha;
final float menuAlpha = 1 - fraction;
if (mMenuState == MENU_STATE_FULL) {
mMenuContainer.setAlpha(menuAlpha);
mSettingsButton.setAlpha(menuAlpha);
mDismissButton.setAlpha(menuAlpha);
final float interpolatedAlpha =
MENU_BACKGROUND_ALPHA * menuAlpha + DISMISS_BACKGROUND_ALPHA * fraction;
alpha = (int) (interpolatedAlpha * 255);
} else {
if (mMenuState == MENU_STATE_CLOSE) {
mDismissButton.setAlpha(menuAlpha);
}
alpha = (int) (fraction * DISMISS_BACKGROUND_ALPHA * 255);
}
mBackgroundDrawable.setAlpha(alpha);
}
private void notifyMenuStateChange(int menuState, boolean resize, Runnable callback) {
mMenuState = menuState;
mController.onMenuStateChanged(menuState, resize, callback);

View File

@@ -385,23 +385,20 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
* Flings the PiP to the closest snap target.
*/
void flingToSnapTarget(
float velocityX, float velocityY,
@Nullable Runnable updateAction, @Nullable Runnable endAction) {
movetoTarget(velocityX, velocityY, updateAction, endAction, false /* isStash */);
float velocityX, float velocityY, @Nullable Runnable endAction) {
movetoTarget(velocityX, velocityY, endAction, false /* isStash */);
}
/**
* Stash PiP to the closest edge.
*/
void stashToEdge(
float velocityX, float velocityY,
@Nullable Runnable updateAction, @Nullable Runnable endAction) {
movetoTarget(velocityX, velocityY, updateAction, endAction, true /* isStash */);
float velocityX, float velocityY, @Nullable Runnable endAction) {
movetoTarget(velocityX, velocityY, endAction, true /* isStash */);
}
private void movetoTarget(
float velocityX, float velocityY,
@Nullable Runnable updateAction, @Nullable Runnable endAction, boolean isStash) {
float velocityX, float velocityY, @Nullable Runnable endAction, boolean isStash) {
// If we're flinging to a snap target now, we're not springing to catch up to the touch
// location now.
mSpringingToTouch = false;
@@ -416,11 +413,6 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
FloatProperties.RECT_Y, velocityY, mFlingConfigY, mSpringConfig)
.withEndActions(endAction);
if (updateAction != null) {
mTemporaryBoundsPhysicsAnimator.addUpdateListener(
(target, values) -> updateAction.run());
}
final float offset = ((float) mBounds.width()) * (1.0f - STASH_RATIO);
final float leftEdge = isStash ? mMovementBounds.left - offset : mMovementBounds.left;
final float rightEdge = isStash ? mMovementBounds.right + offset : mMovementBounds.right;

View File

@@ -26,40 +26,26 @@ import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.TransitionDrawable;
import android.os.Handler;
import android.os.RemoteException;
import android.provider.DeviceConfig;
import android.util.Log;
import android.util.Size;
import android.view.Gravity;
import android.view.IPinnedStackController;
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringForce;
import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.R;
import com.android.wm.shell.animation.PhysicsAnimator;
import com.android.wm.shell.common.DismissCircleView;
import com.android.wm.shell.common.FloatingContentCoordinator;
import com.android.wm.shell.common.magnetictarget.MagnetizedObject;
import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.pip.PipBoundsHandler;
import com.android.wm.shell.pip.PipTaskOrganizer;
@@ -67,8 +53,6 @@ import com.android.wm.shell.pip.PipUiEventLogger;
import java.io.PrintWriter;
import kotlin.Unit;
/**
* Manages all the touch handling for PIP on the Phone, including moving, dismissing and expanding
* the PIP.
@@ -82,14 +66,12 @@ public class PipTouchHandler {
/* The multiplier to apply scale the target size by when applying the magnetic field radius */
private static final float MAGNETIC_FIELD_RADIUS_MULTIPLIER = 1.25f;
// Allow dragging the PIP to a location to close it
private final boolean mEnableDismissDragToEdge;
// Allow PIP to resize to a slightly bigger state upon touch
private final boolean mEnableResize;
private final Context mContext;
private final WindowManager mWindowManager;
private final PipBoundsHandler mPipBoundsHandler;
private final PipUiEventLogger mPipUiEventLogger;
private final PipDismissTargetHandler mPipDismissTargetHandler;
private PipResizeGestureHandler mPipResizeGestureHandler;
private IPinnedStackController mPinnedStackController;
@@ -105,34 +87,6 @@ public class PipTouchHandler {
*/
private boolean mEnableStash = false;
/**
* MagnetizedObject wrapper for PIP. This allows the magnetic target library to locate and move
* PIP.
*/
private MagnetizedObject<Rect> mMagnetizedPip;
/**
* Container for the dismiss circle, so that it can be animated within the container via
* translation rather than within the WindowManager via slow layout animations.
*/
private ViewGroup mTargetViewContainer;
/** Circle view used to render the dismiss target. */
private DismissCircleView mTargetView;
/**
* MagneticTarget instance wrapping the target view and allowing us to set its magnetic radius.
*/
private MagnetizedObject.MagneticTarget mMagneticTarget;
/** PhysicsAnimator instance for animating the dismiss target in/out. */
private PhysicsAnimator<View> mMagneticTargetAnimator;
/** Default configuration to use for springing the dismiss target in/out. */
private final PhysicsAnimator.SpringConfig mTargetSpringConfig =
new PhysicsAnimator.SpringConfig(
SpringForce.STIFFNESS_LOW, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
// The current movement bounds
private Rect mMovementBounds = new Rect();
@@ -150,12 +104,6 @@ public class PipTouchHandler {
private int mDeferResizeToNormalBoundsUntilRotation = -1;
private int mDisplayRotation;
/**
* Runnable that can be posted delayed to show the target. This needs to be saved as a member
* variable so we can pass it to removeCallbacks.
*/
private Runnable mShowTargetAction = this::showDismissTargetMaybe;
private Handler mHandler = new Handler();
// Behaviour states
@@ -163,7 +111,6 @@ public class PipTouchHandler {
private boolean mIsImeShowing;
private int mImeHeight;
private int mImeOffset;
private int mDismissAreaHeight;
private boolean mIsShelfShowing;
private int mShelfHeight;
private int mMovementBoundsExtraOffsets;
@@ -221,7 +168,6 @@ public class PipTouchHandler {
mContext = context;
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
mPipBoundsHandler = pipBoundsHandler;
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mMenuController = menuController;
mMenuController.addListener(new PipMenuListener());
mGesture = new DefaultPipTouchGesture();
@@ -231,13 +177,14 @@ public class PipTouchHandler {
new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper,
pipTaskOrganizer, this::getMovementBounds,
this::updateMovementBounds, pipUiEventLogger, menuController);
mPipDismissTargetHandler = new PipDismissTargetHandler(context, pipUiEventLogger,
mMotionHelper, mHandler);
mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler,
() -> mMenuController.showMenuWithDelay(MENU_STATE_FULL, mMotionHelper.getBounds(),
true /* allowMenuTimeout */, willResizeMenu(), shouldShowResizeHandle()),
menuController::hideMenu);
Resources res = context.getResources();
mEnableDismissDragToEdge = res.getBoolean(R.bool.config_pipEnableDismissDragToEdge);
mEnableResize = res.getBoolean(R.bool.config_pipEnableResizeForMenu);
reloadResources();
@@ -248,61 +195,6 @@ public class PipTouchHandler {
mPipUiEventLogger = pipUiEventLogger;
mTargetView = new DismissCircleView(context);
mTargetViewContainer = new FrameLayout(context);
mTargetViewContainer.setBackgroundDrawable(
context.getDrawable(R.drawable.floating_dismiss_gradient_transition));
mTargetViewContainer.setClipChildren(false);
mTargetViewContainer.addView(mTargetView);
mMagnetizedPip = mMotionHelper.getMagnetizedPip();
mMagneticTarget = mMagnetizedPip.addTarget(mTargetView, 0);
updateMagneticTargetSize();
mMagnetizedPip.setAnimateStuckToTarget(
(target, velX, velY, flung, after) -> {
if (mEnableDismissDragToEdge) {
mMotionHelper.animateIntoDismissTarget(target, velX, velY, flung, after);
}
return Unit.INSTANCE;
});
mMagnetizedPip.setMagnetListener(new MagnetizedObject.MagnetListener() {
@Override
public void onStuckToTarget(@NonNull MagnetizedObject.MagneticTarget target) {
// Show the dismiss target, in case the initial touch event occurred within the
// magnetic field radius.
if (mEnableDismissDragToEdge) {
showDismissTargetMaybe();
}
}
@Override
public void onUnstuckFromTarget(@NonNull MagnetizedObject.MagneticTarget target,
float velX, float velY, boolean wasFlungOut) {
if (wasFlungOut) {
mMotionHelper.flingToSnapTarget(velX, velY, null, null);
hideDismissTarget();
} else {
mMotionHelper.setSpringingToTouch(true);
}
}
@Override
public void onReleasedInTarget(@NonNull MagnetizedObject.MagneticTarget target) {
mMotionHelper.notifyDismissalPending();
mHandler.post(() -> {
mMotionHelper.animateDismiss();
hideDismissTarget();
});
mPipUiEventLogger.log(
PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_DRAG_TO_REMOVE);
}
});
mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView);
mEnableStash = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_SYSTEMUI,
PIP_STASHING,
@@ -323,27 +215,7 @@ public class PipTouchHandler {
mExpandedShortestEdgeSize = res.getDimensionPixelSize(
R.dimen.pip_expanded_shortest_edge_size);
mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
mDismissAreaHeight = res.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height);
updateMagneticTargetSize();
}
private void updateMagneticTargetSize() {
if (mTargetView == null) {
return;
}
final Resources res = mContext.getResources();
final int targetSize = res.getDimensionPixelSize(R.dimen.dismiss_circle_size);
final FrameLayout.LayoutParams newParams =
new FrameLayout.LayoutParams(targetSize, targetSize);
newParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
newParams.bottomMargin = mContext.getResources().getDimensionPixelSize(
R.dimen.floating_dismiss_bottom_margin);
mTargetView.setLayoutParams(newParams);
// Set the magnetic field radius equal to the target size from the center of the target
mMagneticTarget.setMagneticFieldRadiusPx(
(int) (targetSize * MAGNETIC_FIELD_RADIUS_MULTIPLIER));
mPipDismissTargetHandler.updateMagneticTargetSize();
}
private boolean shouldShowResizeHandle() {
@@ -368,7 +240,7 @@ public class PipTouchHandler {
}
public void onActivityPinned() {
createOrUpdateDismissTarget();
mPipDismissTargetHandler.createOrUpdateDismissTarget();
mShowPipMenuOnAnimationEnd = true;
mPipResizeGestureHandler.onActivityPinned();
@@ -378,7 +250,7 @@ public class PipTouchHandler {
public void onActivityUnpinned(ComponentName topPipActivity) {
if (topPipActivity == null) {
// Clean up state after the last PiP activity is removed
cleanUpDismissTarget();
mPipDismissTargetHandler.cleanUpDismissTarget();
mFloatingContentCoordinator.onContentRemoved(mMotionHelper);
}
@@ -409,7 +281,7 @@ public class PipTouchHandler {
reloadResources();
// Recreate the dismiss target for the new orientation.
createOrUpdateDismissTarget();
mPipDismissTargetHandler.createOrUpdateDismissTarget();
}
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
@@ -553,94 +425,6 @@ public class PipTouchHandler {
}
}
/** Adds the magnetic target view to the WindowManager so it's ready to be animated in. */
private void createOrUpdateDismissTarget() {
if (!mTargetViewContainer.isAttachedToWindow()) {
mHandler.removeCallbacks(mShowTargetAction);
mMagneticTargetAnimator.cancel();
mTargetViewContainer.setVisibility(View.INVISIBLE);
try {
mWindowManager.addView(mTargetViewContainer, getDismissTargetLayoutParams());
} catch (IllegalStateException e) {
// This shouldn't happen, but if the target is already added, just update its layout
// params.
mWindowManager.updateViewLayout(
mTargetViewContainer, getDismissTargetLayoutParams());
}
} else {
mWindowManager.updateViewLayout(mTargetViewContainer, getDismissTargetLayoutParams());
}
}
/** Returns layout params for the dismiss target, using the latest display metrics. */
private WindowManager.LayoutParams getDismissTargetLayoutParams() {
final Point windowSize = new Point();
mWindowManager.getDefaultDisplay().getRealSize(windowSize);
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
mDismissAreaHeight,
0, windowSize.y - mDismissAreaHeight,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
lp.setTitle("pip-dismiss-overlay");
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
lp.setFitInsetsTypes(0 /* types */);
return lp;
}
/** Makes the dismiss target visible and animates it in, if it isn't already visible. */
private void showDismissTargetMaybe() {
createOrUpdateDismissTarget();
if (mTargetViewContainer.getVisibility() != View.VISIBLE) {
mTargetView.setTranslationY(mTargetViewContainer.getHeight());
mTargetViewContainer.setVisibility(View.VISIBLE);
// Cancel in case we were in the middle of animating it out.
mMagneticTargetAnimator.cancel();
mMagneticTargetAnimator
.spring(DynamicAnimation.TRANSLATION_Y, 0f, mTargetSpringConfig)
.start();
((TransitionDrawable) mTargetViewContainer.getBackground()).startTransition(
DISMISS_TRANSITION_DURATION_MS);
}
}
/** Animates the magnetic dismiss target out and then sets it to GONE. */
private void hideDismissTarget() {
mHandler.removeCallbacks(mShowTargetAction);
mMagneticTargetAnimator
.spring(DynamicAnimation.TRANSLATION_Y,
mTargetViewContainer.getHeight(),
mTargetSpringConfig)
.withEndActions(() -> mTargetViewContainer.setVisibility(View.GONE))
.start();
((TransitionDrawable) mTargetViewContainer.getBackground()).reverseTransition(
DISMISS_TRANSITION_DURATION_MS);
}
/**
* Removes the dismiss target and cancels any pending callbacks to show it.
*/
private void cleanUpDismissTarget() {
mHandler.removeCallbacks(mShowTargetAction);
if (mTargetViewContainer.isAttachedToWindow()) {
mWindowManager.removeViewImmediate(mTargetViewContainer);
}
}
/**
* TODO Add appropriate description
*/
@@ -650,7 +434,7 @@ public class PipTouchHandler {
if (!isRegistered && mTouchState.isUserInteracting()) {
// If the input consumer is unregistered while the user is interacting, then we may not
// get the final TOUCH_UP event, so clean up the dismiss target as well
cleanUpDismissTarget();
mPipDismissTargetHandler.cleanUpDismissTarget();
}
}
@@ -683,7 +467,7 @@ public class PipTouchHandler {
}
if ((ev.getAction() == MotionEvent.ACTION_DOWN || mTouchState.isUserInteracting())
&& mMagnetizedPip.maybeConsumeMotionEvent(ev)) {
&& mPipDismissTargetHandler.maybeConsumeMotionEvent(ev)) {
// If the first touch event occurs within the magnetic field, pass the ACTION_DOWN event
// to the touch state. Touch state needs a DOWN event in order to later process MOVE
// events it'll receive if the object is dragged out of the magnetic field.
@@ -792,25 +576,6 @@ public class PipTouchHandler {
mAccessibilityManager.sendAccessibilityEvent(event);
}
/**
* Updates the appearance of the menu and scrim on top of the PiP while dismissing.
*/
private void updateDismissFraction() {
if (mMenuController != null) {
Rect bounds = mMotionHelper.getBounds();
final float target = mInsetBounds.bottom;
float fraction = 0f;
if (bounds.bottom > target) {
final float distance = bounds.bottom - target;
fraction = Math.min(distance / bounds.height(), 1f);
}
if (Float.compare(fraction, 0f) != 0 || mMenuController.isMenuVisible()) {
// Update if the fraction > 0, or if fraction == 0 and the menu was already visible
mMenuController.setDismissFraction(fraction);
}
}
}
/**
* Sets the controller to update the system of changes from user interaction.
*/
@@ -958,13 +723,7 @@ public class PipTouchHandler {
if (touchState.startedDragging()) {
mSavedSnapFraction = -1f;
if (mEnableDismissDragToEdge) {
if (mTargetViewContainer.getVisibility() != View.VISIBLE) {
mHandler.removeCallbacks(mShowTargetAction);
showDismissTargetMaybe();
}
}
mPipDismissTargetHandler.showDismissTargetMaybe();
}
if (touchState.isDragging()) {
@@ -995,9 +754,7 @@ public class PipTouchHandler {
@Override
public boolean onUp(PipTouchState touchState) {
if (mEnableDismissDragToEdge) {
hideDismissTarget();
}
mPipDismissTargetHandler.hideDismissTargetMaybe();
if (!touchState.isUserInteracting()) {
return false;
@@ -1023,12 +780,9 @@ public class PipTouchHandler {
if (mEnableStash
&& (animatingBounds.right > mPipBoundsHandler.getDisplayBounds().right
|| animatingBounds.left < mPipBoundsHandler.getDisplayBounds().left)) {
mMotionHelper.stashToEdge(vel.x, vel.y,
PipTouchHandler.this::updateDismissFraction /* updateAction */,
this::flingEndAction /* endAction */);
mMotionHelper.stashToEdge(vel.x, vel.y, this::flingEndAction /* endAction */);
} else {
mMotionHelper.flingToSnapTarget(vel.x, vel.y,
PipTouchHandler.this::updateDismissFraction /* updateAction */,
this::flingEndAction /* endAction */);
}
} else if (mTouchState.isDoubleTap()) {
@@ -1122,7 +876,6 @@ public class PipTouchHandler {
pw.println(innerPrefix + "mIsShelfShowing=" + mIsShelfShowing);
pw.println(innerPrefix + "mShelfHeight=" + mShelfHeight);
pw.println(innerPrefix + "mSavedSnapFraction=" + mSavedSnapFraction);
pw.println(innerPrefix + "mEnableDragToEdgeDismiss=" + mEnableDismissDragToEdge);
pw.println(innerPrefix + "mMovementBoundsExtraOffsets=" + mMovementBoundsExtraOffsets);
mPipBoundsHandler.dump(pw, innerPrefix);
mTouchState.dump(pw, innerPrefix);