PiP pinch-to-resize: add double-tap to max/min size.
Per spec, max size would be the biggest possible bounds within the movement bounds (displayWidth - 2 * insetWidth), and min size would be 40% of the width. This also fixes the issue of portrait PiP not resizing correctly due to wrong math being done in the resize algorithm. Bug: 166478885 Test: Double-tap on PiP Change-Id: I2e239d23a0e2519c0b482005614a1faddb1f808a
This commit is contained in:
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.util.Size;
|
||||
import android.view.DisplayInfo;
|
||||
@@ -59,6 +60,8 @@ public final class PipBoundsState {
|
||||
private final @NonNull Rect mExpandedBounds = new Rect();
|
||||
private final @NonNull Rect mNormalMovementBounds = new Rect();
|
||||
private final @NonNull Rect mExpandedMovementBounds = new Rect();
|
||||
private final Point mMaxSize = new Point();
|
||||
private final Point mMinSize = new Point();
|
||||
private final @NonNull Context mContext;
|
||||
private float mAspectRatio;
|
||||
private int mStashedState = STASH_TYPE_NONE;
|
||||
@@ -151,6 +154,24 @@ public final class PipBoundsState {
|
||||
mExpandedMovementBounds.set(bounds);
|
||||
}
|
||||
|
||||
/** Sets the max possible size for resize. */
|
||||
public void setMaxSize(int width, int height) {
|
||||
mMaxSize.set(width, height);
|
||||
}
|
||||
|
||||
/** Sets the min possible size for resize. */
|
||||
public void setMinSize(int width, int height) {
|
||||
mMinSize.set(width, height);
|
||||
}
|
||||
|
||||
public Point getMaxSize() {
|
||||
return mMaxSize;
|
||||
}
|
||||
|
||||
public Point getMinSize() {
|
||||
return mMinSize;
|
||||
}
|
||||
|
||||
/** Returns the expanded movement bounds. */
|
||||
@NonNull
|
||||
public Rect getExpandedMovementBounds() {
|
||||
|
||||
@@ -85,21 +85,21 @@ public class PipPinchResizingAlgorithm {
|
||||
} else {
|
||||
// Assuming that the width is our target we calculate the height.
|
||||
width1 = Math.max(minVisibleWidth, Math.min(maxSize.x, width));
|
||||
height1 = Math.round((float) width1 * aspect);
|
||||
height1 = Math.round((float) width1 / aspect);
|
||||
if (height1 < minVisibleHeight) {
|
||||
// If the resulting height is too small we adjust to the minimal size.
|
||||
height1 = minVisibleHeight;
|
||||
width1 = Math.max(minVisibleWidth,
|
||||
Math.min(maxSize.x, Math.round((float) height1 / aspect)));
|
||||
Math.min(maxSize.x, Math.round((float) height1 * aspect)));
|
||||
}
|
||||
// Assuming that the height is our target we calculate the width.
|
||||
height2 = Math.max(minVisibleHeight, Math.min(maxSize.y, height));
|
||||
width2 = Math.round((float) height2 / aspect);
|
||||
width2 = Math.round((float) height2 * aspect);
|
||||
if (width2 < minVisibleWidth) {
|
||||
// If the resulting width is too small we adjust to the minimal size.
|
||||
width2 = minVisibleWidth;
|
||||
height2 = Math.max(minVisibleHeight,
|
||||
Math.min(maxSize.y, Math.round((float) width2 * aspect)));
|
||||
Math.min(maxSize.y, Math.round((float) width2 / aspect)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -359,9 +359,13 @@ public class PipTouchHandler {
|
||||
mPipBoundsState.getExpandedBounds(), insetBounds, expandedMovementBounds,
|
||||
bottomOffset);
|
||||
|
||||
mPipResizeGestureHandler.updateMinSize(normalBounds.width(), normalBounds.height());
|
||||
mPipResizeGestureHandler.updateMaxSize(mPipBoundsState.getExpandedBounds().width(),
|
||||
mPipBoundsState.getExpandedBounds().height());
|
||||
if (mPipResizeGestureHandler.isUsingPinchToZoom()) {
|
||||
updatePinchResizeSizeConstraints(insetBounds, normalBounds, aspectRatio);
|
||||
} else {
|
||||
mPipResizeGestureHandler.updateMinSize(normalBounds.width(), normalBounds.height());
|
||||
mPipResizeGestureHandler.updateMaxSize(mPipBoundsState.getExpandedBounds().width(),
|
||||
mPipBoundsState.getExpandedBounds().height());
|
||||
}
|
||||
|
||||
// The extra offset does not really affect the movement bounds, but are applied based on the
|
||||
// current state (ime showing, or shelf offset) when we need to actually shift
|
||||
@@ -430,6 +434,30 @@ public class PipTouchHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePinchResizeSizeConstraints(Rect insetBounds, Rect normalBounds,
|
||||
float aspectRatio) {
|
||||
final int shorterLength = Math.min(mPipBoundsState.getDisplayBounds().width(),
|
||||
mPipBoundsState.getDisplayBounds().height());
|
||||
final int padding = insetBounds.left;
|
||||
final int minWidth, minHeight, maxWidth, maxHeight;
|
||||
if (aspectRatio > 1f) {
|
||||
minWidth = (int) Math.min(normalBounds.width(), shorterLength * 0.4);
|
||||
minHeight = (int) (minWidth / aspectRatio);
|
||||
maxWidth = (int) Math.max(normalBounds.width(), shorterLength - 2 * padding);
|
||||
maxHeight = (int) (maxWidth / aspectRatio);
|
||||
} else {
|
||||
minHeight = (int) Math.min(normalBounds.height(), shorterLength * 0.4);
|
||||
minWidth = (int) (minHeight * aspectRatio);
|
||||
maxHeight = (int) Math.max(normalBounds.height(), shorterLength - 2 * padding);
|
||||
maxWidth = (int) (maxHeight * aspectRatio);
|
||||
}
|
||||
|
||||
mPipResizeGestureHandler.updateMinSize(minWidth, minHeight);
|
||||
mPipResizeGestureHandler.updateMaxSize(maxWidth, maxHeight);
|
||||
mPipBoundsState.setMaxSize(maxWidth, maxHeight);
|
||||
mPipBoundsState.setMinSize(minWidth, minHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO Add appropriate description
|
||||
*/
|
||||
@@ -640,13 +668,36 @@ public class PipTouchHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private void animateToExpandedState(Runnable callback) {
|
||||
Rect expandedBounds = new Rect(mPipBoundsState.getExpandedBounds());
|
||||
mSavedSnapFraction = mMotionHelper.animateToExpandedState(expandedBounds,
|
||||
mPipBoundsState.getMovementBounds(), mPipBoundsState.getExpandedMovementBounds(),
|
||||
private void animateToMaximizedState(Runnable callback) {
|
||||
Rect maxMovementBounds = new Rect();
|
||||
Rect maxBounds = new Rect(0, 0, mPipBoundsState.getMaxSize().x,
|
||||
mPipBoundsState.getMaxSize().y);
|
||||
mPipBoundsAlgorithm.getMovementBounds(maxBounds, mInsetBounds, maxMovementBounds,
|
||||
mIsImeShowing ? mImeHeight : 0);
|
||||
mSavedSnapFraction = mMotionHelper.animateToExpandedState(maxBounds,
|
||||
mPipBoundsState.getMovementBounds(), maxMovementBounds,
|
||||
callback);
|
||||
}
|
||||
|
||||
private void animateToMinimizedState() {
|
||||
animateToUnexpandedState(new Rect(0, 0, mPipBoundsState.getMinSize().x,
|
||||
mPipBoundsState.getMinSize().y));
|
||||
}
|
||||
|
||||
private void animateToExpandedState(Runnable callback) {
|
||||
mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds());
|
||||
final Rect currentBounds = mPipBoundsState.getBounds();
|
||||
final Rect expandedBounds = mPipBoundsState.getExpandedBounds();
|
||||
Rect finalExpandedBounds = new Rect(expandedBounds.width() > expandedBounds.width()
|
||||
&& expandedBounds.height() > expandedBounds.height()
|
||||
? currentBounds : expandedBounds);
|
||||
Rect restoredMovementBounds = new Rect();
|
||||
mPipBoundsAlgorithm.getMovementBounds(finalExpandedBounds,
|
||||
mInsetBounds, restoredMovementBounds, mIsImeShowing ? mImeHeight : 0);
|
||||
mSavedSnapFraction = mMotionHelper.animateToExpandedState(finalExpandedBounds,
|
||||
mPipBoundsState.getMovementBounds(), restoredMovementBounds, callback);
|
||||
}
|
||||
|
||||
private void animateToUnexpandedState(Rect restoreBounds) {
|
||||
Rect restoredMovementBounds = new Rect();
|
||||
mPipBoundsAlgorithm.getMovementBounds(restoreBounds,
|
||||
@@ -789,17 +840,15 @@ public class PipTouchHandler {
|
||||
// If using pinch to zoom, double-tap functions as resizing between max/min size
|
||||
if (mPipResizeGestureHandler.isUsingPinchToZoom()) {
|
||||
final boolean toExpand = mPipBoundsState.getBounds().width()
|
||||
< mPipBoundsState.getExpandedBounds().width()
|
||||
< mPipBoundsState.getMaxSize().x
|
||||
&& mPipBoundsState.getBounds().height()
|
||||
< mPipBoundsState.getExpandedBounds().height();
|
||||
mPipResizeGestureHandler.setUserResizeBounds(toExpand
|
||||
? mPipBoundsState.getExpandedBounds()
|
||||
: mPipBoundsState.getNormalBounds());
|
||||
< mPipBoundsState.getMaxSize().y;
|
||||
if (toExpand) {
|
||||
animateToExpandedState(null);
|
||||
animateToMaximizedState(null);
|
||||
} else {
|
||||
animateToUnexpandedState(mPipBoundsState.getNormalBounds());
|
||||
animateToMinimizedState();
|
||||
}
|
||||
mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds());
|
||||
} else {
|
||||
// Expand to fullscreen if this is a double tap
|
||||
// the PiP should be frozen until the transition ends
|
||||
|
||||
Reference in New Issue
Block a user