From 37d6b6d53abefede1a82954b2699ce746781dd0c Mon Sep 17 00:00:00 2001 From: Matt Casey Date: Wed, 24 Feb 2021 15:30:47 -0500 Subject: [PATCH] Make CropView handle images that aren't full-height Compute the ImageView's extra top and bottom padding when it gets a drawable or does layout, pass that information to CropView to adjust its boundaries accordingly. Also give MagnifierView some elevation so it doesn't get obscured by the buttons. Bug: 180967209 Test: Take a long screenshot at the top of the settings app, observe that the image isn't full height, ensure that crop handles properly honor image bounds and those bounds are honored on export as well. Change-Id: Iac859995b362724a0db00b666a6ff970a0ccba1d --- .../SystemUI/res/layout/long_screenshot.xml | 2 +- .../android/systemui/screenshot/CropView.java | 36 +++++++++++++++---- .../screenshot/LongScreenshotActivity.java | 25 +++++++++++++ 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/packages/SystemUI/res/layout/long_screenshot.xml b/packages/SystemUI/res/layout/long_screenshot.xml index e2f3e2a306e38..7ba28a8483c39 100644 --- a/packages/SystemUI/res/layout/long_screenshot.xml +++ b/packages/SystemUI/res/layout/long_screenshot.xml @@ -76,7 +76,6 @@ android:layout_height="wrap_content" android:layout_marginBottom="42dp" android:layout_marginHorizontal="48dp" - android:adjustViewBounds="true" app:layout_constrainedHeight="true" app:layout_constrainedWidth="true" app:layout_constraintTop_toBottomOf="@id/guideline" @@ -110,6 +109,7 @@ android:visibility="invisible" android:layout_width="200dp" android:layout_height="200dp" + android:elevation="2dp" app:layout_constraintTop_toBottomOf="@id/guideline" app:layout_constraintLeft_toLeftOf="parent" app:handleThickness="@dimen/screenshot_crop_handle_thickness" diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java index 5b55864eed8a5..c066619d049a8 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java @@ -65,6 +65,9 @@ public class CropView extends View { private float mTopDelta = 0f; private float mBottomDelta = 0f; + private int mExtraTopPadding; + private int mExtraBottomPadding; + private CropBoundary mCurrentDraggingBoundary = CropBoundary.NONE; private float mStartingY; // y coordinate of ACTION_DOWN private CropInteractionListener mCropInteractionListener; @@ -117,12 +120,13 @@ public class CropView extends View { if (mCurrentDraggingBoundary != CropBoundary.NONE) { float delta = event.getY() - mStartingY; if (mCurrentDraggingBoundary == CropBoundary.TOP) { - mTopDelta = pixelsToFraction((int) MathUtils.constrain(delta, -topPx, + mTopDelta = pixelDistanceToFraction((int) MathUtils.constrain(delta, + -topPx + mExtraTopPadding, bottomPx - 2 * mCropTouchMargin - topPx)); } else { // Bottom - mBottomDelta = pixelsToFraction((int) MathUtils.constrain(delta, + mBottomDelta = pixelDistanceToFraction((int) MathUtils.constrain(delta, topPx + 2 * mCropTouchMargin - bottomPx, - getHeight() - bottomPx)); + getHeight() - bottomPx - mExtraBottomPadding)); } updateListener(event); invalidate(); @@ -194,6 +198,16 @@ public class CropView extends View { animator.start(); } + /** + * Set additional top and bottom padding for the image being cropped (used when the + * corresponding ImageView doesn't take the full height). + */ + public void setExtraPadding(int top, int bottom) { + mExtraTopPadding = top; + mExtraBottomPadding = bottom; + invalidate(); + } + /** * @return value [0,1] representing the position of the top crop boundary. Does not reflect * changes from any in-progress touch input. @@ -244,12 +258,22 @@ public class CropView extends View { true, mHandlePaint); } + /** + * Convert the given fraction position to pixel position within the View. + */ private int fractionToPixels(float frac) { - return (int) (frac * getHeight()); + return (int) (mExtraTopPadding + frac * getImageHeight()); } - private float pixelsToFraction(int px) { - return px / (float) getHeight(); + private int getImageHeight() { + return getHeight() - mExtraTopPadding - mExtraBottomPadding; + } + + /** + * Convert the given pixel distance to fraction of the image. + */ + private float pixelDistanceToFraction(int px) { + return px / (float) getImageHeight(); } private CropBoundary nearestBoundary(MotionEvent event, int topPx, int bottomPx) { diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java index 5a13ea55222d7..4dc846e0e95d1 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java @@ -157,6 +157,9 @@ public class LongScreenshotActivity extends Activity { }); } } + mPreview.addOnLayoutChangeListener( + (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> + updateCropLocation()); } @Override @@ -305,6 +308,27 @@ public class LongScreenshotActivity extends Activity { } } + private void updateCropLocation() { + Drawable drawable = mPreview.getDrawable(); + if (drawable == null) { + return; + } + + float imageRatio = drawable.getBounds().width() / (float) drawable.getBounds().height(); + float viewRatio = mPreview.getWidth() / (float) mPreview.getHeight(); + + if (imageRatio > viewRatio) { + // Image is full width and height is constrained, compute extra padding to inform + // CropView + float imageHeight = mPreview.getHeight() * viewRatio / imageRatio; + int extraPadding = (int) (mPreview.getHeight() - imageHeight) / 2; + mCropView.setExtraPadding(extraPadding, extraPadding); + } else { + // Image is full height + mCropView.setExtraPadding(0, 0); + } + } + private void doCapture() { mScrollCaptureController.start(mConnection, new ScrollCaptureController.ScrollCaptureCallback() { @@ -319,6 +343,7 @@ public class LongScreenshotActivity extends Activity { Log.i(TAG, "Got tiles " + imageTileSet.getWidth() + " x " + imageTileSet.getHeight()); mPreview.setImageDrawable(imageTileSet.getDrawable()); + updateCropLocation(); mMagnifierView.setDrawable(imageTileSet.getDrawable(), imageTileSet.getWidth(), imageTileSet.getHeight()); mCropView.animateBoundaryTo(CropView.CropBoundary.BOTTOM, 0.5f);