diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml
index 5bd181c824923..93bd58113bc28 100644
--- a/packages/SystemUI/res/layout/global_screenshot.xml
+++ b/packages/SystemUI/res/layout/global_screenshot.xml
@@ -20,6 +20,11 @@
android:theme="@style/Screenshot"
android:layout_width="match_parent"
android:layout_height="match_parent">
+
+
diff --git a/packages/SystemUI/res/layout/long_screenshot.xml b/packages/SystemUI/res/layout/long_screenshot.xml
index 8e30aecd6a279..0c6baec6b781b 100644
--- a/packages/SystemUI/res/layout/long_screenshot.xml
+++ b/packages/SystemUI/res/layout/long_screenshot.xml
@@ -62,6 +62,7 @@
android:paddingHorizontal="48dp"
android:paddingTop="8dp"
android:paddingBottom="42dp"
+ android:alpha="0"
app:layout_constrainedHeight="true"
app:layout_constrainedWidth="true"
app:layout_constraintTop_toBottomOf="@id/save"
@@ -72,6 +73,16 @@
tools:minHeight="100dp"
tools:minWidth="100dp" />
+
+
viewRatio) {
// Image is full width and height is constrained, compute extra padding to inform
// CropView
imageHeight = (int) (previewHeight * viewRatio / imageRatio);
- int extraPadding = (previewHeight - imageHeight) / 2;
+ extraPadding = (previewHeight - imageHeight) / 2;
mCropView.setExtraPadding(extraPadding + mPreview.getPaddingTop(),
extraPadding + mPreview.getPaddingBottom());
imageTop += (previewHeight - imageHeight) / 2;
mCropView.setExtraPadding(extraPadding, extraPadding);
mCropView.setImageWidth(previewWidth);
+ scale = previewWidth / (float) mPreview.getDrawable().getIntrinsicWidth();
} else {
imageWidth = (int) (previewWidth * imageRatio / viewRatio);
imageLeft += (previewWidth - imageWidth) / 2;
// Image is full height
mCropView.setExtraPadding(mPreview.getPaddingTop(), mPreview.getPaddingBottom());
mCropView.setImageWidth((int) (previewHeight * imageRatio));
+ scale = previewHeight / (float) mPreview.getDrawable().getIntrinsicHeight();
}
// Update transition view's position and scale.
@@ -439,5 +475,20 @@ public class LongScreenshotActivity extends Activity {
params.width = boundaries.width();
params.height = boundaries.height();
mTransitionView.setLayoutParams(params);
+
+ ConstraintLayout.LayoutParams enterTransitionParams =
+ (ConstraintLayout.LayoutParams) mEnterTransitionView.getLayoutParams();
+ float topFraction = Math.max(0,
+ -mLongScreenshot.getTop() / (float) mLongScreenshot.getHeight());
+ enterTransitionParams.width = (int) (scale * drawable.getIntrinsicWidth());
+ enterTransitionParams.height = (int) (scale * mLongScreenshot.getPageHeight());
+ mEnterTransitionView.setLayoutParams(enterTransitionParams);
+
+ Matrix matrix = new Matrix();
+ matrix.setScale(scale, scale);
+ matrix.postTranslate(0, -scale * drawable.getIntrinsicHeight() * topFraction);
+ mEnterTransitionView.setImageMatrix(matrix);
+ mEnterTransitionView.setTranslationY(
+ topFraction * previewHeight + mPreview.getPaddingTop() + extraPadding);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 1f9221c2956f4..fa4daf2299310 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -603,7 +603,7 @@ public class ScreenshotController {
// No connection means that the target window wasn't found
// or that it cannot support scroll capture.
Log.d(TAG, "ScrollCapture: " + mLastScrollCaptureResponse.getDescription() + " ["
- + mLastScrollCaptureResponse.getWindowTitle() + "]");
+ + mLastScrollCaptureResponse.getWindowTitle() + "]");
return;
}
Log.d(TAG, "ScrollCapture: connected to window ["
@@ -611,6 +611,7 @@ public class ScreenshotController {
final ScrollCaptureResponse response = mLastScrollCaptureResponse;
mScreenshotView.showScrollChip(/* onClick */ () -> {
+ mScreenshotView.prepareScrollingTransition(response, mScreenBitmap);
// Clear the reference to prevent close() in dismissScreenshot
mLastScrollCaptureResponse = null;
final ListenableFuture future =
@@ -628,9 +629,14 @@ public class ScreenshotController {
final Intent intent = new Intent(mContext, LongScreenshotActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- mContext.startActivity(intent);
- dismissScreenshot(false);
+ Pair transition =
+ ActivityOptions.startSharedElementAnimation(
+ mWindow, new ScreenshotExitTransitionCallbacks(), null,
+ Pair.create(mScreenshotView.getScrollablePreview(),
+ ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME));
+ transition.second.startExit();
+ mContext.startActivity(intent, transition.first.toBundle());
}, mMainExecutor);
});
} catch (CancellationException e) {
@@ -654,7 +660,8 @@ public class ScreenshotController {
}
@Override
- public void onWindowDetached() { }
+ public void onWindowDetached() {
+ }
});
}
@@ -852,24 +859,9 @@ public class ScreenshotController {
*/
private Supplier getActionTransitionSupplier() {
return () -> {
- ExitTransitionCallbacks cb = new ExitTransitionCallbacks() {
- @Override
- public boolean isReturnTransitionAllowed() {
- return false;
- }
-
- @Override
- public void hideSharedElements() {
- finishDismiss();
- }
-
- @Override
- public void onFinish() {
- }
- };
-
Pair transition =
- ActivityOptions.startSharedElementAnimation(mWindow, cb, null,
+ ActivityOptions.startSharedElementAnimation(
+ mWindow, new ScreenshotExitTransitionCallbacks(), null,
Pair.create(mScreenshotView.getScreenshotPreview(),
ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME));
transition.second.startExit();
@@ -955,4 +947,20 @@ public class ScreenshotController {
}
return matchWithinTolerance;
}
+
+ private class ScreenshotExitTransitionCallbacks implements ExitTransitionCallbacks {
+ @Override
+ public boolean isReturnTransitionAllowed() {
+ return false;
+ }
+
+ @Override
+ public void hideSharedElements() {
+ finishDismiss();
+ }
+
+ @Override
+ public void onFinish() {
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index facebee52943f..3e7601e9351bf 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -40,6 +40,7 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Insets;
+import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
@@ -57,6 +58,7 @@ import android.util.MathUtils;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
+import android.view.ScrollCaptureResponse;
import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewGroup;
@@ -71,6 +73,8 @@ import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ActionTransition;
@@ -125,9 +129,11 @@ public class ScreenshotView extends FrameLayout implements
private boolean mDirectionLTR;
private ScreenshotSelectorView mScreenshotSelectorView;
+ private ImageView mScrollingScrim;
private View mScreenshotStatic;
private ImageView mScreenshotPreview;
private View mScreenshotPreviewBorder;
+ private ImageView mScrollablePreview;
private ImageView mScreenshotFlash;
private ImageView mActionsContainerBackground;
private HorizontalScrollView mActionsContainer;
@@ -262,6 +268,7 @@ public class ScreenshotView extends FrameLayout implements
@Override // View
protected void onFinishInflate() {
+ mScrollingScrim = requireNonNull(findViewById(R.id.screenshot_scrolling_scrim));
mScreenshotStatic = requireNonNull(findViewById(R.id.global_screenshot_static));
mScreenshotPreview = requireNonNull(findViewById(R.id.global_screenshot_preview));
mScreenshotPreviewBorder = requireNonNull(
@@ -275,6 +282,7 @@ public class ScreenshotView extends FrameLayout implements
mBackgroundProtection = requireNonNull(
findViewById(R.id.global_screenshot_actions_background));
mDismissButton = requireNonNull(findViewById(R.id.global_screenshot_dismiss_button));
+ mScrollablePreview = requireNonNull(findViewById(R.id.screenshot_scrollable_preview));
mScreenshotFlash = requireNonNull(findViewById(R.id.global_screenshot_flash));
mScreenshotSelectorView = requireNonNull(findViewById(R.id.global_screenshot_selector));
mShareChip = requireNonNull(mActionsContainer.findViewById(R.id.screenshot_share_chip));
@@ -323,6 +331,10 @@ public class ScreenshotView extends FrameLayout implements
return mScreenshotPreview;
}
+ View getScrollablePreview() {
+ return mScrollablePreview;
+ }
+
/**
* Set up the logger and callback on dismissal.
*
@@ -672,6 +684,38 @@ public class ScreenshotView extends FrameLayout implements
}
}
+ private Rect scrollableAreaOnScreen(ScrollCaptureResponse response) {
+ Rect r = new Rect(response.getBoundsInWindow());
+ Rect windowInScreen = response.getWindowBounds();
+ r.offset(windowInScreen.left, windowInScreen.top);
+ r.intersect(new Rect(0, 0, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
+ return r;
+ }
+
+ void prepareScrollingTransition(ScrollCaptureResponse response, Bitmap screenBitmap) {
+ Rect scrollableArea = scrollableAreaOnScreen(response);
+ float scale = mCornerSizeX
+ / (mOrientationPortrait ? screenBitmap.getWidth() : screenBitmap.getHeight());
+ ConstraintLayout.LayoutParams params =
+ (ConstraintLayout.LayoutParams) mScrollablePreview.getLayoutParams();
+
+ params.width = (int) (scale * scrollableArea.width());
+ params.height = (int) (scale * scrollableArea.height());
+ Matrix matrix = new Matrix();
+ matrix.setScale(scale, scale);
+ matrix.postTranslate(0, -scrollableArea.top * scale);
+
+ mScrollablePreview.setTranslationX(scale * scrollableArea.left);
+ mScrollablePreview.setTranslationY(scale * scrollableArea.top);
+ mScrollablePreview.setImageMatrix(matrix);
+
+ mScrollingScrim.setImageBitmap(screenBitmap);
+ mScrollingScrim.setVisibility(View.VISIBLE);
+ mScrollablePreview.setImageBitmap(screenBitmap);
+ mScrollablePreview.setVisibility(View.VISIBLE);
+ createScreenshotFadeDismissAnimation(true).start();
+ }
+
boolean isDismissing() {
return (mDismissAnimation != null && mDismissAnimation.isRunning());
}
@@ -772,7 +816,7 @@ public class ScreenshotView extends FrameLayout implements
transition.action.actionIntent.send();
// fade out non-preview UI
- createScreenshotFadeDismissAnimation().start();
+ createScreenshotFadeDismissAnimation(false).start();
} catch (PendingIntent.CanceledException e) {
mPendingSharedTransition = false;
if (transition.onCancelRunnable != null) {
@@ -810,7 +854,7 @@ public class ScreenshotView extends FrameLayout implements
return animSet;
}
- private ValueAnimator createScreenshotFadeDismissAnimation() {
+ ValueAnimator createScreenshotFadeDismissAnimation(boolean fadePreview) {
ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1);
alphaAnim.addUpdateListener(animation -> {
float alpha = 1 - animation.getAnimatedFraction();
@@ -818,6 +862,10 @@ public class ScreenshotView extends FrameLayout implements
mActionsContainerBackground.setAlpha(alpha);
mActionsContainer.setAlpha(alpha);
mBackgroundProtection.setAlpha(alpha);
+ mScreenshotPreviewBorder.setAlpha(alpha);
+ if (fadePreview) {
+ mScreenshotPreview.setAlpha(alpha);
+ }
});
alphaAnim.setDuration(600);
return alphaAnim;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java
index 2863074bee0a9..94e3149487797 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureClient.java
@@ -405,6 +405,10 @@ public class ScrollCaptureClient {
return new Rect(mWindowBounds);
}
+ public Rect getBoundsInWindow() {
+ return new Rect(mBoundsInWindow);
+ }
+
@Override
public int getMaxTiles() {
return mMaxTiles;