diff --git a/packages/SystemUI/res/layout/long_screenshot.xml b/packages/SystemUI/res/layout/long_screenshot.xml
index 4765b44d78c87..3f4baaf27b840 100644
--- a/packages/SystemUI/res/layout/long_screenshot.xml
+++ b/packages/SystemUI/res/layout/long_screenshot.xml
@@ -99,6 +99,7 @@
app:handleThickness="@dimen/screenshot_crop_handle_thickness"
app:handleColor="?androidprv:attr/colorAccentPrimary"
app:scrimColor="@color/screenshot_crop_scrim"
+ app:containerBackgroundColor="?android:colorBackgroundFloating"
tools:background="?android:colorBackground"
tools:minHeight="100dp"
tools:minWidth="100dp" />
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 067d56f3d157c..d2ed6017b2055 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -143,6 +143,7 @@
+
@@ -178,6 +179,7 @@
+
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
index 9e11451afa064..0a60f6da159e6 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/CropView.java
@@ -62,6 +62,7 @@ public class CropView extends View {
private final float mCropTouchMargin;
private final Paint mShadePaint;
private final Paint mHandlePaint;
+ private final Paint mContainerBackgroundPaint;
// Crop rect with each element represented as [0,1] along its proper axis.
private RectF mCrop = new RectF(0, 0, 1, 1);
@@ -79,6 +80,9 @@ public class CropView extends View {
// The allowable values for the current boundary being dragged
private Range mMotionRange;
+ // Value [0,1] indicating progress in animateEntrance()
+ private float mEntranceInterpolation = 1f;
+
private CropInteractionListener mCropInteractionListener;
private final ExploreByTouchHelper mExploreByTouchHelper;
@@ -92,6 +96,9 @@ public class CropView extends View {
attrs, R.styleable.CropView, 0, 0);
mShadePaint = new Paint();
mShadePaint.setColor(t.getColor(R.styleable.CropView_scrimColor, Color.TRANSPARENT));
+ mContainerBackgroundPaint = new Paint();
+ mContainerBackgroundPaint.setColor(t.getColor(R.styleable.CropView_containerBackgroundColor,
+ Color.TRANSPARENT));
mHandlePaint = new Paint();
mHandlePaint.setColor(t.getColor(R.styleable.CropView_handleColor, Color.BLACK));
mHandlePaint.setStrokeCap(Paint.Cap.ROUND);
@@ -125,10 +132,22 @@ public class CropView extends View {
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
- drawShade(canvas, 0, 0, 1, mCrop.top);
- drawShade(canvas, 0, mCrop.bottom, 1, 1);
+ // Top and bottom borders reflect the boundary between the (scrimmed) image and the
+ // opaque container background. This is only meaningful during an entrance transition.
+ float topBorder = MathUtils.lerp(mCrop.top, 0, mEntranceInterpolation);
+ float bottomBorder = MathUtils.lerp(mCrop.bottom, 1, mEntranceInterpolation);
+ drawShade(canvas, 0, topBorder, 1, mCrop.top);
+ drawShade(canvas, 0, mCrop.bottom, 1, bottomBorder);
drawShade(canvas, 0, mCrop.top, mCrop.left, mCrop.bottom);
drawShade(canvas, mCrop.right, mCrop.top, 1, mCrop.bottom);
+
+ // Entrance transition expects the crop bounds to be full width, so we only draw container
+ // background on the top and bottom.
+ drawContainerBackground(canvas, 0, 0, 1, topBorder);
+ drawContainerBackground(canvas, 0, bottomBorder, 1, 1);
+
+ mHandlePaint.setAlpha((int) (mEntranceInterpolation * 255));
+
drawHorizontalHandle(canvas, mCrop.top, /* draw the handle tab up */ true);
drawHorizontalHandle(canvas, mCrop.bottom, /* draw the handle tab down */ false);
drawVerticalHandle(canvas, mCrop.left, /* left */ true);
@@ -281,6 +300,22 @@ public class CropView extends View {
animator.start();
}
+ /**
+ * Fade in crop bounds, animate reveal of cropped-out area from current crop bounds.
+ */
+ public void animateEntrance() {
+ mEntranceInterpolation = 0;
+ ValueAnimator animator = new ValueAnimator();
+ animator.addUpdateListener(animation -> {
+ mEntranceInterpolation = animation.getAnimatedFraction();
+ invalidate();
+ });
+ animator.setFloatValues(0f, 1f);
+ animator.setDuration(750);
+ animator.setInterpolator(new FastOutSlowInInterpolator());
+ animator.start();
+ }
+
/**
* Set additional top and bottom padding for the image being cropped (used when the
* corresponding ImageView doesn't take the full height).
@@ -369,6 +404,13 @@ public class CropView extends View {
fractionToVerticalPixels(bottom), mShadePaint);
}
+ private void drawContainerBackground(Canvas canvas, float left, float top, float right,
+ float bottom) {
+ canvas.drawRect(fractionToHorizontalPixels(left), fractionToVerticalPixels(top),
+ fractionToHorizontalPixels(right),
+ fractionToVerticalPixels(bottom), mContainerBackgroundPaint);
+ }
+
private void drawHorizontalHandle(Canvas canvas, float frac, boolean handleTabUp) {
int y = fractionToVerticalPixels(frac);
canvas.drawLine(fractionToHorizontalPixels(mCrop.left), y,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
index 2a427f7671582..25ec1d74008e9 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -192,7 +192,6 @@ public class LongScreenshotActivity extends Activity {
mLongScreenshot = longScreenshot;
Drawable drawable = mLongScreenshot.getDrawable();
mPreview.setImageDrawable(drawable);
- mCropView.setVisibility(View.VISIBLE);
mMagnifierView.setDrawable(mLongScreenshot.getDrawable(),
mLongScreenshot.getWidth(), mLongScreenshot.getHeight());
// Original boundaries go from the image tile set's y=0 to y=pageSize, so
@@ -219,10 +218,12 @@ public class LongScreenshotActivity extends Activity {
public void onTransitionEnd(Transition transition) {
super.onTransitionEnd(transition);
mPreview.animate().alpha(1f);
- mCropView.animateBoundaryTo(
+ mCropView.setBoundaryPosition(
CropView.CropBoundary.TOP, topFraction);
- mCropView.animateBoundaryTo(
+ mCropView.setBoundaryPosition(
CropView.CropBoundary.BOTTOM, bottomFraction);
+ mCropView.animateEntrance();
+ mCropView.setVisibility(View.VISIBLE);
setButtonsEnabled(true);
mEnterTransitionView.setVisibility(View.GONE);
}