From beeaf5589d4fbd92038f1a6cd3aa4941cf884841 Mon Sep 17 00:00:00 2001 From: Mihai Popa Date: Thu, 19 Jul 2018 15:50:43 +0100 Subject: [PATCH] [Magnifier-48] Allow on-the-fly zoom update The CL adds Magnifier#setZoom(float), which allows dynamically changing the initial zoom applied to the content that will be magnified and displayed in the magnifier. Bug: 72211470 Test: manual testing Test: atest CtsWidgetTestCases:android.widget.cts.MagnifierTest Change-Id: I1dd01085ef5a1589a3602aefd03223d1451564f5 --- api/current.txt | 1 + api/test-current.txt | 1 + core/java/android/widget/Magnifier.java | 52 +++++++++++++++++++++---- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/api/current.txt b/api/current.txt index cc4e36f3e1107..c07ea98ebda50 100644 --- a/api/current.txt +++ b/api/current.txt @@ -52977,6 +52977,7 @@ package android.widget { method public int getSourceWidth(); method public int getWidth(); method public float getZoom(); + method public void setZoom(float); method public void show(float, float); method public void show(float, float, float, float); method public void update(); diff --git a/api/test-current.txt b/api/test-current.txt index bb3cb1f2239e3..b8cee4be0b846 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1545,6 +1545,7 @@ package android.widget { public final class Magnifier { method public android.graphics.Bitmap getContent(); method public static android.graphics.PointF getMagnifierDefaultSize(); + method public android.graphics.Bitmap getOriginalContent(); method public void setOnOperationCompleteCallback(android.widget.Magnifier.Callback); } diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java index f82b17f62b32e..3280d477b23d6 100644 --- a/core/java/android/widget/Magnifier.java +++ b/core/java/android/widget/Magnifier.java @@ -77,11 +77,13 @@ public final class Magnifier { // The height of the window containing the magnifier. private final int mWindowHeight; // The zoom applied to the view region copied to the magnifier view. - private final float mZoom; + private float mZoom; // The width of the content that will be copied to the magnifier. - private final int mSourceWidth; + private int mSourceWidth; // The height of the content that will be copied to the magnifier. - private final int mSourceHeight; + private int mSourceHeight; + // Whether the zoom of the magnifier has changed since last content copy. + private boolean mDirtyZoom; // The elevation of the window containing the magnifier. private final float mWindowElevation; // The corner radius of the window containing the magnifier. @@ -196,7 +198,8 @@ public final class Magnifier { final int startX = mClampedCenterZoomCoords.x - mSourceWidth / 2; final int startY = mClampedCenterZoomCoords.y - mSourceHeight / 2; - if (sourceCenterX != mPrevShowSourceCoords.x || sourceCenterY != mPrevShowSourceCoords.y) { + if (sourceCenterX != mPrevShowSourceCoords.x || sourceCenterY != mPrevShowSourceCoords.y + || mDirtyZoom) { if (mWindow == null) { synchronized (mLock) { mWindow = new InternalPopupWindow(mView.getContext(), mView.getDisplay(), @@ -253,9 +256,16 @@ public final class Magnifier { public void update() { if (mWindow != null) { obtainSurfaces(); - // Update the content shown in the magnifier. - performPixelCopy(mPrevStartCoordsInSurface.x, mPrevStartCoordsInSurface.y, - false /* update window position */); + if (!mDirtyZoom) { + // Update the content shown in the magnifier. + performPixelCopy(mPrevStartCoordsInSurface.x, mPrevStartCoordsInSurface.y, + false /* update window position */); + } else { + // If the zoom has changed, we cannot use the same top left coordinates + // as before, so just #show again to have them recomputed. + show(mPrevShowSourceCoords.x, mPrevShowSourceCoords.y, + mPrevShowWindowCoords.x, mPrevShowWindowCoords.y); + } } } @@ -297,6 +307,18 @@ public final class Magnifier { return mSourceHeight; } + /** + * Sets the zoom to be applied to the chosen content before being copied to the magnifier popup. + * @param zoom the zoom to be set + */ + public void setZoom(@FloatRange(from = 0f) float zoom) { + Preconditions.checkArgumentPositive(zoom, "Zoom should be positive"); + mZoom = zoom; + mSourceWidth = Math.round(mWindowWidth / mZoom); + mSourceHeight = Math.round(mWindowHeight / mZoom); + mDirtyZoom = true; + } + /** * Returns the zoom to be applied to the magnified view region copied to the magnifier. * If the zoom is x and the magnifier window size is (width, height), the original size @@ -534,6 +556,7 @@ public final class Magnifier { sPixelCopyHandlerThread.getThreadHandler()); mPrevStartCoordsInSurface.x = startXInSurface; mPrevStartCoordsInSurface.y = startYInSurface; + mDirtyZoom = false; } /** @@ -1019,6 +1042,21 @@ public final class Magnifier { } } + /** + * @return the content to be magnified, as bitmap + * + * @hide + */ + @TestApi + public @Nullable Bitmap getOriginalContent() { + if (mWindow == null) { + return null; + } + synchronized (mWindow.mLock) { + return Bitmap.createBitmap(mWindow.mBitmap); + } + } + /** * @return the size of the magnifier window in dp *