Merge changes I5c096c2b,If0d0d86b into sc-dev am: 73eb2771f8
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14751471 Change-Id: Ib5743c5f8f200d904573eff541667b645f33bbf1
This commit is contained in:
@@ -1,28 +0,0 @@
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<!--
|
||||
The transparent circle outline that encircles the bubbles when they're in the dismiss target.
|
||||
-->
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#66FFFFFF" />
|
||||
|
||||
<solid android:color="#B3000000" />
|
||||
</shape>
|
||||
@@ -1,26 +0,0 @@
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<!-- The 'X' bubble dismiss icon. This is just ic_close with a stroke. -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24.0dp"
|
||||
android:height="24.0dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:pathData="M19.000000,6.400000l-1.400000,-1.400000 -5.600000,5.600000 -5.600000,-5.600000 -1.400000,1.400000 5.600000,5.600000 -5.600000,5.600000 1.400000,1.400000 5.600000,-5.600000 5.600000,5.600000 1.400000,-1.400000 -5.600000,-5.600000z"
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:strokeColor="#FF000000"/>
|
||||
</vector>
|
||||
@@ -20,9 +20,8 @@
|
||||
android:shape="oval">
|
||||
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#AAFFFFFF" />
|
||||
|
||||
<solid android:color="#77000000" />
|
||||
android:width="2dp"
|
||||
android:color="@android:color/system_accent1_600" />
|
||||
|
||||
<solid android:color="@android:color/system_accent1_600" />
|
||||
</shape>
|
||||
@@ -21,5 +21,5 @@
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:pathData="M19.000000,6.400000l-1.400000,-1.400000 -5.600000,5.600000 -5.600000,-5.600000 -1.400000,1.400000 5.600000,5.600000 -5.600000,5.600000 1.400000,1.400000 5.600000,-5.600000 5.600000,5.600000 1.400000,-1.400000 -5.600000,-5.600000z"
|
||||
android:fillColor="#FFFFFFFF"/>
|
||||
android:fillColor="@android:color/system_neutral1_50"/>
|
||||
</vector>
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
<!--
|
||||
~ Copyright (C) 2019 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
|
||||
-->
|
||||
<!-- Bubble dismiss target consisting of an X icon and the text 'Dismiss'. -->
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/floating_dismiss_gradient_height"
|
||||
android:layout_gravity="bottom|center_horizontal">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/bubble_dismiss_circle"
|
||||
android:layout_width="@dimen/bubble_dismiss_encircle_size"
|
||||
android:layout_height="@dimen/bubble_dismiss_encircle_size"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/bubble_dismiss_circle" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/bubble_dismiss_icon_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="@dimen/bubble_dismiss_target_padding_y"
|
||||
android:paddingTop="@dimen/bubble_dismiss_target_padding_y"
|
||||
android:paddingLeft="@dimen/bubble_dismiss_target_padding_x"
|
||||
android:paddingRight="@dimen/bubble_dismiss_target_padding_x"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bubble_dismiss_close_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/bubble_dismiss_icon" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
@@ -15,7 +15,8 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<dimen name="dismiss_circle_size">52dp</dimen>
|
||||
<dimen name="dismiss_circle_size">96dp</dimen>
|
||||
<dimen name="dismiss_circle_small">60dp</dimen>
|
||||
|
||||
<!-- The height of the gradient indicating the dismiss edge when moving a PIP. -->
|
||||
<dimen name="floating_dismiss_gradient_height">250dp</dimen>
|
||||
|
||||
@@ -34,10 +34,7 @@ import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
@@ -192,8 +189,7 @@ public class BubbleStackView extends FrameLayout
|
||||
private final BubbleController mBubbleController;
|
||||
private final BubbleData mBubbleData;
|
||||
|
||||
private final ValueAnimator mDesaturateAndDarkenAnimator;
|
||||
private final Paint mDesaturateAndDarkenPaint = new Paint();
|
||||
private final ValueAnimator mDismissBubbleAnimator;
|
||||
|
||||
private PhysicsAnimationLayout mBubbleContainer;
|
||||
private StackAnimationController mStackAnimationController;
|
||||
@@ -330,8 +326,8 @@ public class BubbleStackView extends FrameLayout
|
||||
private boolean mIsExpansionAnimating = false;
|
||||
private boolean mIsBubbleSwitchAnimating = false;
|
||||
|
||||
/** The view to desaturate/darken when magneted to the dismiss target. */
|
||||
@Nullable private View mDesaturateAndDarkenTargetView;
|
||||
/** The view to shrink and apply alpha to when magneted to the dismiss target. */
|
||||
@Nullable private View mViewBeingDismissed;
|
||||
|
||||
private Rect mTempRect = new Rect();
|
||||
|
||||
@@ -415,8 +411,7 @@ public class BubbleStackView extends FrameLayout
|
||||
if (mExpandedAnimationController.getDraggedOutBubble() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
animateDesaturateAndDarken(
|
||||
animateDismissBubble(
|
||||
mExpandedAnimationController.getDraggedOutBubble(), true);
|
||||
}
|
||||
|
||||
@@ -426,8 +421,7 @@ public class BubbleStackView extends FrameLayout
|
||||
if (mExpandedAnimationController.getDraggedOutBubble() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
animateDesaturateAndDarken(
|
||||
animateDismissBubble(
|
||||
mExpandedAnimationController.getDraggedOutBubble(), false);
|
||||
|
||||
if (wasFlungOut) {
|
||||
@@ -459,14 +453,13 @@ public class BubbleStackView extends FrameLayout
|
||||
@Override
|
||||
public void onStuckToTarget(
|
||||
@NonNull MagnetizedObject.MagneticTarget target) {
|
||||
animateDesaturateAndDarken(mBubbleContainer, true);
|
||||
animateDismissBubble(mBubbleContainer, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnstuckFromTarget(@NonNull MagnetizedObject.MagneticTarget target,
|
||||
float velX, float velY, boolean wasFlungOut) {
|
||||
animateDesaturateAndDarken(mBubbleContainer, false);
|
||||
|
||||
animateDismissBubble(mBubbleContainer, false);
|
||||
if (wasFlungOut) {
|
||||
mStackAnimationController.flingStackThenSpringToEdge(
|
||||
mStackAnimationController.getStackPosition().x, velX, velY);
|
||||
@@ -481,11 +474,10 @@ public class BubbleStackView extends FrameLayout
|
||||
mStackAnimationController.animateStackDismissal(
|
||||
mDismissView.getHeight() /* translationYBy */,
|
||||
() -> {
|
||||
resetDesaturationAndDarken();
|
||||
resetDismissAnimator();
|
||||
dismissMagnetizedObject();
|
||||
}
|
||||
);
|
||||
|
||||
mDismissView.hide();
|
||||
}
|
||||
};
|
||||
@@ -836,17 +828,7 @@ public class BubbleStackView extends FrameLayout
|
||||
.setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY));
|
||||
mFlyoutTransitionSpring.addEndListener(mAfterFlyoutTransitionSpring);
|
||||
|
||||
mDismissView = new DismissView(context);
|
||||
addView(mDismissView);
|
||||
|
||||
final ContentResolver contentResolver = getContext().getContentResolver();
|
||||
final int dismissRadius = Settings.Secure.getInt(
|
||||
contentResolver, "bubble_dismiss_radius", mBubbleSize * 2 /* default */);
|
||||
|
||||
// Save the MagneticTarget instance for the newly set up view - we'll add this to the
|
||||
// MagnetizedObjects.
|
||||
mMagneticTarget = new MagnetizedObject.MagneticTarget(
|
||||
mDismissView.getCircle(), dismissRadius);
|
||||
setUpDismissView();
|
||||
|
||||
setClipChildren(false);
|
||||
setFocusable(true);
|
||||
@@ -891,6 +873,7 @@ public class BubbleStackView extends FrameLayout
|
||||
mRelativeStackPositionBeforeRotation = null;
|
||||
}
|
||||
|
||||
setUpDismissView();
|
||||
if (mIsExpanded) {
|
||||
// Re-draw bubble row and pointer for new orientation.
|
||||
beforeExpandedViewAnimation();
|
||||
@@ -905,30 +888,23 @@ public class BubbleStackView extends FrameLayout
|
||||
}
|
||||
removeOnLayoutChangeListener(mOrientationChangedListener);
|
||||
};
|
||||
|
||||
final ColorMatrix animatedMatrix = new ColorMatrix();
|
||||
final ColorMatrix darkenMatrix = new ColorMatrix();
|
||||
|
||||
mDesaturateAndDarkenAnimator = ValueAnimator.ofFloat(1f, 0f);
|
||||
mDesaturateAndDarkenAnimator.addUpdateListener(animation -> {
|
||||
final float maxDismissSize = getResources().getDimensionPixelSize(
|
||||
R.dimen.dismiss_circle_size);
|
||||
final float minDismissSize = getResources().getDimensionPixelSize(
|
||||
R.dimen.dismiss_circle_small);
|
||||
final float sizePercent = minDismissSize / maxDismissSize;
|
||||
mDismissBubbleAnimator = ValueAnimator.ofFloat(1f, 0f);
|
||||
mDismissBubbleAnimator.addUpdateListener(animation -> {
|
||||
final float animatedValue = (float) animation.getAnimatedValue();
|
||||
animatedMatrix.setSaturation(animatedValue);
|
||||
|
||||
final float animatedDarkenValue = (1f - animatedValue) * DARKEN_PERCENT;
|
||||
darkenMatrix.setScale(
|
||||
1f - animatedDarkenValue /* red */,
|
||||
1f - animatedDarkenValue /* green */,
|
||||
1f - animatedDarkenValue /* blue */,
|
||||
1f /* alpha */);
|
||||
|
||||
// Concat the matrices so that the animatedMatrix both desaturates and darkens.
|
||||
animatedMatrix.postConcat(darkenMatrix);
|
||||
|
||||
// Update the paint and apply it to the bubble container.
|
||||
mDesaturateAndDarkenPaint.setColorFilter(new ColorMatrixColorFilter(animatedMatrix));
|
||||
|
||||
if (mDesaturateAndDarkenTargetView != null) {
|
||||
mDesaturateAndDarkenTargetView.setLayerPaint(mDesaturateAndDarkenPaint);
|
||||
if (mDismissView != null) {
|
||||
mDismissView.setPivotX((mDismissView.getRight() - mDismissView.getLeft()) / 2f);
|
||||
mDismissView.setPivotY((mDismissView.getBottom() - mDismissView.getTop()) / 2f);
|
||||
final float scaleValue = Math.max(animatedValue, sizePercent);
|
||||
mDismissView.getCircle().setScaleX(scaleValue);
|
||||
mDismissView.getCircle().setScaleY(scaleValue);
|
||||
}
|
||||
if (mViewBeingDismissed != null) {
|
||||
mViewBeingDismissed.setAlpha(Math.max(animatedValue, 0.7f));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1048,6 +1024,23 @@ public class BubbleStackView extends FrameLayout
|
||||
}
|
||||
};
|
||||
|
||||
private void setUpDismissView() {
|
||||
if (mDismissView != null) {
|
||||
removeView(mDismissView);
|
||||
}
|
||||
mDismissView = new DismissView(getContext());
|
||||
addView(mDismissView);
|
||||
|
||||
final ContentResolver contentResolver = getContext().getContentResolver();
|
||||
final int dismissRadius = Settings.Secure.getInt(
|
||||
contentResolver, "bubble_dismiss_radius", mBubbleSize * 2 /* default */);
|
||||
|
||||
// Save the MagneticTarget instance for the newly set up view - we'll add this to the
|
||||
// MagnetizedObjects.
|
||||
mMagneticTarget = new MagnetizedObject.MagneticTarget(
|
||||
mDismissView.getCircle(), dismissRadius);
|
||||
}
|
||||
|
||||
// TODO: Create ManageMenuView and move setup / animations there
|
||||
private void setUpManageMenu() {
|
||||
if (mManageMenu != null) {
|
||||
@@ -1217,6 +1210,7 @@ public class BubbleStackView extends FrameLayout
|
||||
public void onThemeChanged() {
|
||||
setUpFlyout();
|
||||
setUpManageMenu();
|
||||
setUpDismissView();
|
||||
updateOverflow();
|
||||
updateUserEdu();
|
||||
updateExpandedViewTheme();
|
||||
@@ -1256,6 +1250,7 @@ public class BubbleStackView extends FrameLayout
|
||||
updateOverflow();
|
||||
setUpManageMenu();
|
||||
setUpFlyout();
|
||||
setUpDismissView();
|
||||
mBubbleSize = mPositioner.getBubbleSize();
|
||||
for (Bubble b : mBubbleData.getBubbles()) {
|
||||
if (b.getIconView() == null) {
|
||||
@@ -2264,42 +2259,46 @@ public class BubbleStackView extends FrameLayout
|
||||
}
|
||||
}
|
||||
|
||||
/** Prepares and starts the desaturate/darken animation on the bubble stack. */
|
||||
private void animateDesaturateAndDarken(View targetView, boolean desaturateAndDarken) {
|
||||
mDesaturateAndDarkenTargetView = targetView;
|
||||
/** Prepares and starts the dismiss animation on the bubble stack. */
|
||||
private void animateDismissBubble(View targetView, boolean applyAlpha) {
|
||||
mViewBeingDismissed = targetView;
|
||||
|
||||
if (mDesaturateAndDarkenTargetView == null) {
|
||||
if (mViewBeingDismissed == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (desaturateAndDarken) {
|
||||
// Use the animated paint for the bubbles.
|
||||
mDesaturateAndDarkenTargetView.setLayerType(
|
||||
View.LAYER_TYPE_HARDWARE, mDesaturateAndDarkenPaint);
|
||||
mDesaturateAndDarkenAnimator.removeAllListeners();
|
||||
mDesaturateAndDarkenAnimator.start();
|
||||
if (applyAlpha) {
|
||||
mDismissBubbleAnimator.removeAllListeners();
|
||||
mDismissBubbleAnimator.start();
|
||||
} else {
|
||||
mDesaturateAndDarkenAnimator.removeAllListeners();
|
||||
mDesaturateAndDarkenAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
mDismissBubbleAnimator.removeAllListeners();
|
||||
mDismissBubbleAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
// Stop using the animated paint.
|
||||
resetDesaturationAndDarken();
|
||||
resetDismissAnimator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
super.onAnimationCancel(animation);
|
||||
resetDismissAnimator();
|
||||
}
|
||||
});
|
||||
mDesaturateAndDarkenAnimator.reverse();
|
||||
mDismissBubbleAnimator.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
private void resetDesaturationAndDarken() {
|
||||
private void resetDismissAnimator() {
|
||||
mDismissBubbleAnimator.removeAllListeners();
|
||||
mDismissBubbleAnimator.cancel();
|
||||
|
||||
mDesaturateAndDarkenAnimator.removeAllListeners();
|
||||
mDesaturateAndDarkenAnimator.cancel();
|
||||
|
||||
if (mDesaturateAndDarkenTargetView != null) {
|
||||
mDesaturateAndDarkenTargetView.setLayerType(View.LAYER_TYPE_NONE, null);
|
||||
mDesaturateAndDarkenTargetView = null;
|
||||
if (mViewBeingDismissed != null) {
|
||||
mViewBeingDismissed.setAlpha(1f);
|
||||
mViewBeingDismissed = null;
|
||||
}
|
||||
if (mDismissView != null) {
|
||||
mDismissView.getCircle().setScaleX(1f);
|
||||
mDismissView.getCircle().setScaleY(1f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,8 +67,6 @@ class DismissView(context: Context) : FrameLayout(context) {
|
||||
fun show() {
|
||||
if (isShowing) return
|
||||
isShowing = true
|
||||
bringToFront()
|
||||
setZ(Short.MAX_VALUE - 1f)
|
||||
setVisibility(View.VISIBLE)
|
||||
(getBackground() as TransitionDrawable).startTransition(DISMISS_SCRIM_FADE_MS)
|
||||
animator.cancel()
|
||||
|
||||
@@ -379,6 +379,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
}
|
||||
}
|
||||
|
||||
public SurfaceControl getSurfaceControl() {
|
||||
return mLeash;
|
||||
}
|
||||
|
||||
private void setBoundsStateForEntry(ComponentName componentName, PictureInPictureParams params,
|
||||
ActivityInfo activityInfo) {
|
||||
mPipBoundsState.setBoundsStateForEntry(componentName,
|
||||
|
||||
@@ -26,8 +26,10 @@ import android.graphics.Rect;
|
||||
import android.graphics.drawable.TransitionDrawable;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
@@ -47,7 +49,7 @@ import kotlin.Unit;
|
||||
/**
|
||||
* Handler of all Magnetized Object related code for PiP.
|
||||
*/
|
||||
public class PipDismissTargetHandler {
|
||||
public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListener {
|
||||
|
||||
/* 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;
|
||||
@@ -92,6 +94,9 @@ public class PipDismissTargetHandler {
|
||||
private int mDismissAreaHeight;
|
||||
private float mMagneticFieldRadiusPercent = 1f;
|
||||
|
||||
private SurfaceControl mTaskLeash;
|
||||
private boolean mHasDismissTargetSurface;
|
||||
|
||||
private final Context mContext;
|
||||
private final PipMotionHelper mMotionHelper;
|
||||
private final PipUiEventLogger mPipUiEventLogger;
|
||||
@@ -167,6 +172,14 @@ public class PipDismissTargetHandler {
|
||||
mMagneticTargetAnimator = PhysicsAnimator.getInstance(mTargetView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
mTargetViewContainer.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
mHasDismissTargetSurface = true;
|
||||
updateDismissTargetLayer();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Potentially start consuming future motion events if PiP is currently near the magnetized
|
||||
* object.
|
||||
@@ -207,12 +220,31 @@ public class PipDismissTargetHandler {
|
||||
* MAGNETIC_FIELD_RADIUS_MULTIPLIER));
|
||||
}
|
||||
|
||||
public void setTaskLeash(SurfaceControl taskLeash) {
|
||||
mTaskLeash = taskLeash;
|
||||
}
|
||||
|
||||
private void updateDismissTargetLayer() {
|
||||
if (!mHasDismissTargetSurface || mTaskLeash == null) {
|
||||
// No dismiss target surface, can just return
|
||||
return;
|
||||
}
|
||||
|
||||
// Put the dismiss target behind the task
|
||||
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
t.setRelativeLayer(mTargetViewContainer.getViewRootImpl().getSurfaceControl(),
|
||||
mTaskLeash, -1);
|
||||
t.apply();
|
||||
}
|
||||
|
||||
/** Adds the magnetic target view to the WindowManager so it's ready to be animated in. */
|
||||
public void createOrUpdateDismissTarget() {
|
||||
if (!mTargetViewContainer.isAttachedToWindow()) {
|
||||
mMagneticTargetAnimator.cancel();
|
||||
|
||||
mTargetViewContainer.setVisibility(View.INVISIBLE);
|
||||
mTargetViewContainer.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
mHasDismissTargetSurface = false;
|
||||
|
||||
try {
|
||||
mWindowManager.addView(mTargetViewContainer, getDismissTargetLayoutParams());
|
||||
@@ -259,9 +291,9 @@ public class PipDismissTargetHandler {
|
||||
createOrUpdateDismissTarget();
|
||||
|
||||
if (mTargetViewContainer.getVisibility() != View.VISIBLE) {
|
||||
|
||||
mTargetView.setTranslationY(mTargetViewContainer.getHeight());
|
||||
mTargetViewContainer.setVisibility(View.VISIBLE);
|
||||
mTargetViewContainer.getViewTreeObserver().addOnPreDrawListener(this);
|
||||
|
||||
// Cancel in case we were in the middle of animating it out.
|
||||
mMagneticTargetAnimator.cancel();
|
||||
|
||||
@@ -40,6 +40,7 @@ import android.view.Choreographer;
|
||||
import androidx.dynamicanimation.animation.AnimationHandler;
|
||||
import androidx.dynamicanimation.animation.AnimationHandler.FrameCallbackScheduler;
|
||||
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.animation.FloatProperties;
|
||||
import com.android.wm.shell.animation.PhysicsAnimator;
|
||||
import com.android.wm.shell.common.FloatingContentCoordinator;
|
||||
@@ -71,6 +72,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
|
||||
|
||||
/** Friction to use for PIP when it moves via physics fling animations. */
|
||||
private static final float DEFAULT_FRICTION = 1.9f;
|
||||
/** How much of the dismiss circle size to use when scaling down PIP. **/
|
||||
private static final float DISMISS_CIRCLE_PERCENT = 0.85f;
|
||||
|
||||
private final Context mContext;
|
||||
private final PipTaskOrganizer mPipTaskOrganizer;
|
||||
@@ -296,9 +299,17 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
|
||||
boolean flung, Function0<Unit> after) {
|
||||
final PointF targetCenter = target.getCenterOnScreen();
|
||||
|
||||
final float desiredWidth = getBounds().width() / 2;
|
||||
final float desiredHeight = getBounds().height() / 2;
|
||||
// PIP should fit in the circle
|
||||
final float dismissCircleSize = mContext.getResources().getDimensionPixelSize(
|
||||
R.dimen.dismiss_circle_size);
|
||||
|
||||
final float width = getBounds().width();
|
||||
final float height = getBounds().height();
|
||||
final float ratio = width / height;
|
||||
|
||||
// Width should be a little smaller than the circle size.
|
||||
final float desiredWidth = dismissCircleSize * DISMISS_CIRCLE_PERCENT;
|
||||
final float desiredHeight = desiredWidth / ratio;
|
||||
final float destinationX = targetCenter.x - (desiredWidth / 2f);
|
||||
final float destinationY = targetCenter.y - (desiredHeight / 2f);
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ public class PipTouchHandler {
|
||||
private final @NonNull PipBoundsState mPipBoundsState;
|
||||
private final PipUiEventLogger mPipUiEventLogger;
|
||||
private final PipDismissTargetHandler mPipDismissTargetHandler;
|
||||
private final PipTaskOrganizer mPipTaskOrganizer;
|
||||
private final ShellExecutor mMainExecutor;
|
||||
|
||||
private PipResizeGestureHandler mPipResizeGestureHandler;
|
||||
@@ -173,6 +174,7 @@ public class PipTouchHandler {
|
||||
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
|
||||
mPipBoundsAlgorithm = pipBoundsAlgorithm;
|
||||
mPipBoundsState = pipBoundsState;
|
||||
mPipTaskOrganizer = pipTaskOrganizer;
|
||||
mMenuController = menuController;
|
||||
mPipUiEventLogger = pipUiEventLogger;
|
||||
mFloatingContentCoordinator = floatingContentCoordinator;
|
||||
@@ -799,6 +801,7 @@ public class PipTouchHandler {
|
||||
mMovementWithinDismiss = touchState.getDownTouchPosition().y
|
||||
>= mPipBoundsState.getMovementBounds().bottom;
|
||||
mMotionHelper.setSpringingToTouch(false);
|
||||
mPipDismissTargetHandler.setTaskLeash(mPipTaskOrganizer.getSurfaceControl());
|
||||
|
||||
// If the menu is still visible then just poke the menu
|
||||
// so that it will timeout after the user stops touching it
|
||||
@@ -847,6 +850,7 @@ public class PipTouchHandler {
|
||||
@Override
|
||||
public boolean onUp(PipTouchState touchState) {
|
||||
mPipDismissTargetHandler.hideDismissTargetMaybe();
|
||||
mPipDismissTargetHandler.setTaskLeash(null);
|
||||
|
||||
if (!touchState.isUserInteracting()) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user