summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/res/layout/global_screenshot.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java121
3 files changed, 126 insertions, 41 deletions
diff --git a/packages/SystemUI/res/layout/global_screenshot.xml b/packages/SystemUI/res/layout/global_screenshot.xml
index 2bf41d2472be..3c58d16b9552 100644
--- a/packages/SystemUI/res/layout/global_screenshot.xml
+++ b/packages/SystemUI/res/layout/global_screenshot.xml
@@ -39,5 +39,6 @@
android:layout_height="match_parent"
android:visibility="gone"
android:pointerIcon="crosshair"/>
- <include layout="@layout/global_screenshot_static"/>
+ <include layout="@layout/global_screenshot_static"
+ android:id="@+id/global_screenshot_static"/>
</com.android.systemui.screenshot.ScreenshotView>
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 6a4e93be0fe5..3f163d3fc108 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -84,6 +84,7 @@ import javax.inject.Inject;
*/
public class ScreenshotController {
private static final String TAG = logTag(ScreenshotController.class);
+
/**
* POD used in the AsyncTask which saves an image in the background.
*/
@@ -350,10 +351,20 @@ public class ScreenshotController {
// Inflate the screenshot layout
mScreenshotView = (ScreenshotView)
LayoutInflater.from(mContext).inflate(R.layout.global_screenshot, null);
- mScreenshotView.init(mUiEventLogger, this::resetScreenshotView);
+ mScreenshotView.init(mUiEventLogger, new ScreenshotView.ScreenshotViewCallback() {
+ @Override
+ public void onUserInteraction() {
+ resetTimeout();
+ }
+
+ @Override
+ public void onDismiss() {
+ resetScreenshotView();
+ }
+ });
// TODO(159460485): Remove this when focus is handled properly in the system
- mScreenshotView.setOnTouchListener((v, event) -> {
+ mDecorView.setOnTouchListener((v, event) -> {
if (event.getActionMasked() == MotionEvent.ACTION_OUTSIDE) {
if (DEBUG_INPUT) {
Log.d(TAG, "onTouch: ACTION_OUTSIDE");
@@ -432,7 +443,7 @@ public class ScreenshotController {
}
if (DEBUG_WINDOW) {
Log.d(TAG, "saveScreenshot: screenshotView is already attached, resetting. "
- + "(dismissing=" + mScreenshotView.isDismissing() + ")");
+ + "(dismissing=" + mScreenshotView.isDismissing() + ")");
}
mScreenshotView.reset();
}
@@ -580,11 +591,8 @@ public class ScreenshotController {
mSaveInBgTask.execute();
}
- /**
- * Sets up the action shade and its entrance animation, once we get the screenshot URI.
- */
- private void showUiOnActionsReady(ScreenshotController.SavedImageData imageData) {
- logSuccessOnActionsReady(imageData);
+ private void resetTimeout() {
+ mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
AccessibilityManager accessibilityManager = (AccessibilityManager)
mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
@@ -592,12 +600,25 @@ public class ScreenshotController {
SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS,
AccessibilityManager.FLAG_CONTENT_CONTROLS);
- if (DEBUG_UI) {
- Log.d(TAG, "Showing UI actions, dismiss timeout: " + timeoutMs + " ms");
- }
mScreenshotHandler.sendMessageDelayed(
mScreenshotHandler.obtainMessage(MESSAGE_CORNER_TIMEOUT),
timeoutMs);
+ if (DEBUG_UI) {
+ Log.d(TAG, "dismiss timeout: " + timeoutMs + " ms");
+ }
+
+ }
+
+ /**
+ * Sets up the action shade and its entrance animation, once we get the screenshot URI.
+ */
+ private void showUiOnActionsReady(ScreenshotController.SavedImageData imageData) {
+ logSuccessOnActionsReady(imageData);
+ if (DEBUG_UI) {
+ Log.d(TAG, "Showing UI actions");
+ }
+
+ resetTimeout();
if (imageData.uri != null) {
mScreenshotHandler.post(() -> {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index cce60f9c7c9d..4ca3dccf229c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -58,6 +58,7 @@ import android.util.MathUtils;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
+import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
@@ -83,6 +84,12 @@ import java.util.function.Consumer;
public class ScreenshotView extends FrameLayout implements
ViewTreeObserver.OnComputeInternalInsetsListener {
+ interface ScreenshotViewCallback {
+ void onUserInteraction();
+
+ void onDismiss();
+ }
+
private static final String TAG = logTag(ScreenshotView.class);
private static final long SCREENSHOT_FLASH_IN_DURATION_MS = 133;
@@ -99,6 +106,7 @@ public class ScreenshotView extends FrameLayout implements
private static final long SCREENSHOT_DISMISS_ALPHA_OFFSET_MS = 50; // delay before starting fade
private static final float SCREENSHOT_ACTIONS_START_SCALE_X = .7f;
private static final float ROUNDED_CORNER_RADIUS = .05f;
+ private static final int SWIPE_PADDING_DP = 12; // extra padding around views to allow swipe
private final Interpolator mAccelerateInterpolator = new AccelerateInterpolator();
@@ -115,6 +123,7 @@ public class ScreenshotView extends FrameLayout implements
private boolean mDirectionLTR;
private ScreenshotSelectorView mScreenshotSelectorView;
+ private View mScreenshotStatic;
private ImageView mScreenshotPreview;
private ImageView mScreenshotFlash;
private ImageView mActionsContainerBackground;
@@ -127,7 +136,7 @@ public class ScreenshotView extends FrameLayout implements
private ScreenshotActionChip mScrollChip;
private UiEventLogger mUiEventLogger;
- private Runnable mOnDismissRunnable;
+ private ScreenshotViewCallback mCallbacks;
private Animator mDismissAnimation;
private final ArrayList<ScreenshotActionChip> mSmartChips = new ArrayList<>();
@@ -195,8 +204,10 @@ public class ScreenshotView extends FrameLayout implements
final Rect tmpRect = new Rect();
mScreenshotPreview.getBoundsOnScreen(tmpRect);
+ tmpRect.inset((int) dpToPx(-SWIPE_PADDING_DP), (int) dpToPx(-SWIPE_PADDING_DP));
touchRegion.op(tmpRect, Region.Op.UNION);
- mActionsContainer.getBoundsOnScreen(tmpRect);
+ mActionsContainerBackground.getBoundsOnScreen(tmpRect);
+ tmpRect.inset((int) dpToPx(-SWIPE_PADDING_DP), (int) dpToPx(-SWIPE_PADDING_DP));
touchRegion.op(tmpRect, Region.Op.UNION);
mDismissButton.getBoundsOnScreen(tmpRect);
touchRegion.op(tmpRect, Region.Op.UNION);
@@ -215,7 +226,9 @@ public class ScreenshotView extends FrameLayout implements
@Override // View
protected void onFinishInflate() {
+ mScreenshotStatic = requireNonNull(findViewById(R.id.global_screenshot_static));
mScreenshotPreview = requireNonNull(findViewById(R.id.global_screenshot_preview));
+
mActionsContainerBackground = requireNonNull(findViewById(
R.id.global_screenshot_actions_container_background));
mActionsContainer = requireNonNull(findViewById(R.id.global_screenshot_actions_container));
@@ -238,6 +251,16 @@ public class ScreenshotView extends FrameLayout implements
}
});
+ int swipePaddingPx = (int) dpToPx(SWIPE_PADDING_DP);
+ TouchDelegate previewDelegate = new TouchDelegate(
+ new Rect(swipePaddingPx, swipePaddingPx, swipePaddingPx, swipePaddingPx),
+ mScreenshotPreview);
+ mScreenshotPreview.setTouchDelegate(previewDelegate);
+ TouchDelegate actionsDelegate = new TouchDelegate(
+ new Rect(swipePaddingPx, swipePaddingPx, swipePaddingPx, swipePaddingPx),
+ mActionsContainerBackground);
+ mActionsContainerBackground.setTouchDelegate(actionsDelegate);
+
setFocusable(true);
mScreenshotSelectorView.setFocusable(true);
mScreenshotSelectorView.setFocusableInTouchMode(true);
@@ -272,9 +295,9 @@ public class ScreenshotView extends FrameLayout implements
* Note: must be called before any other (non-constructor) method or null pointer exceptions
* may occur.
*/
- void init(UiEventLogger uiEventLogger, Runnable onDismissRunnable) {
+ void init(UiEventLogger uiEventLogger, ScreenshotViewCallback callbacks) {
mUiEventLogger = uiEventLogger;
- mOnDismissRunnable = onDismissRunnable;
+ mCallbacks = callbacks;
}
void takePartialScreenshot(Consumer<Rect> onPartialScreenshotSelected) {
@@ -414,8 +437,14 @@ public class ScreenshotView extends FrameLayout implements
mScreenshotPreview.setX(finalPos.x - bounds.width() * cornerScale / 2f);
mScreenshotPreview.setY(finalPos.y - bounds.height() * cornerScale / 2f);
requestLayout();
- mScreenshotPreview.setOnTouchListener(new SwipeDismissHandler());
+
createScreenshotActionsShadeAnimation().start();
+
+ SwipeDismissHandler swipeDismissHandler = new SwipeDismissHandler();
+ mScreenshotPreview.setOnTouchListener(swipeDismissHandler);
+ mActionsContainer.setOnTouchListener(swipeDismissHandler);
+ mActionsContainerBackground.setOnTouchListener(swipeDismissHandler);
+ mBackgroundProtection.setOnTouchListener(swipeDismissHandler);
}
});
@@ -544,6 +573,7 @@ public class ScreenshotView extends FrameLayout implements
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED);
animateDismissal();
});
+ actionChip.setAlpha(1);
mActionsView.addView(actionChip);
mSmartChips.add(actionChip);
}
@@ -583,7 +613,7 @@ public class ScreenshotView extends FrameLayout implements
if (DEBUG_ANIM) {
Log.d(TAG, "after dismiss animation, calling onDismissRunnable.run()");
}
- mOnDismissRunnable.run();
+ mCallbacks.onDismiss();
}
}
});
@@ -617,7 +647,7 @@ public class ScreenshotView extends FrameLayout implements
mDismissButton.setVisibility(View.GONE);
mScreenshotPreview.setVisibility(View.GONE);
mScreenshotPreview.setLayerType(View.LAYER_TYPE_NONE, null);
- mScreenshotPreview.setTranslationX(0);
+ mScreenshotStatic.setTranslationX(0);
mScreenshotPreview.setTranslationY(0);
mScreenshotPreview.setContentDescription(
mContext.getResources().getString(R.string.screenshot_preview_description));
@@ -675,7 +705,7 @@ public class ScreenshotView extends FrameLayout implements
BitmapDrawable bitmapDrawable = new BitmapDrawable(res, bitmap);
if (insettedHeight == 0 || insettedWidth == 0 || bitmap.getWidth() == 0
|| bitmap.getHeight() == 0) {
- Log.e(TAG, "Can't create inset drawable, using 0 insets bitmap and insets create "
+ Log.e(TAG, "Can't create inset drawable, using 0 insets bitmap and insets create "
+ "degenerate region: " + bitmap.getWidth() + "x" + bitmap.getHeight() + " "
+ bitmapDrawable);
return bitmapDrawable;
@@ -697,6 +727,10 @@ public class ScreenshotView extends FrameLayout implements
}
}
+ private float dpToPx(float dp) {
+ return dp * mDisplayMetrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
+ }
+
class SwipeDismissHandler implements OnTouchListener {
// if distance moved on ACTION_UP is less than this, register a click
@@ -707,11 +741,17 @@ public class ScreenshotView extends FrameLayout implements
private final GestureDetector mGestureDetector;
private final float mDismissStartX;
+ private final Rect mActionsRect = new Rect();
private float mStartX;
private float mStartY;
private float mTranslationX = 0;
+ // tracks whether mStartX has been set for this interaction
+ private boolean mInteractionStarted = false;
+ // tracks whether we're dragging the UI (as opposed to scrolling the actions bar)
+ private boolean mIsDragging = false;
+
SwipeDismissHandler() {
GestureDetector.OnGestureListener gestureListener = new SwipeDismissGestureListener();
mGestureDetector = new GestureDetector(mContext, gestureListener);
@@ -720,10 +760,16 @@ public class ScreenshotView extends FrameLayout implements
@Override
public boolean onTouch(View v, MotionEvent event) {
+ boolean gestureResult = mGestureDetector.onTouchEvent(event);
+ mCallbacks.onUserInteraction();
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mInteractionStarted = true;
mStartX = event.getRawX();
mStartY = event.getRawY();
+ return true;
} else if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+ mInteractionStarted = false;
+ mIsDragging = false;
if (isPastDismissThreshold()
&& (mDismissAnimation == null || !mDismissAnimation.isRunning())) {
if (DEBUG_INPUT) {
@@ -745,18 +791,45 @@ public class ScreenshotView extends FrameLayout implements
return true;
}
}
- return mGestureDetector.onTouchEvent(event);
+ return gestureResult;
}
class SwipeDismissGestureListener extends GestureDetector.SimpleOnGestureListener {
+ /**
+ * This is somewhat complicated to handle because we want to allow scrolling the actions
+ * bar (if it extends off the screen) as well as dismissing the UI horizontally by
+ * dragging the actions bar. In addition, we don't get the initial ACTION_DOWN because
+ * it is consumed by the action bar view.
+ *
+ * So, we use a gated system: first, keep track of the pointer location as we move;
+ * next, check whether the actions bar can scroll in the direction we're moving in. If
+ * it can, let the actions bar handle the event; otherwise, we've gone as far as we can
+ * and can start dragging the UI instead.
+ */
@Override
public boolean onScroll(
MotionEvent ev1, MotionEvent ev2, float distanceX, float distanceY) {
- mTranslationX = ev2.getRawX() - ev1.getRawX();
- mScreenshotPreview.setTranslationX(mTranslationX);
- mDismissButton.setX(mDismissStartX + mTranslationX);
- return true;
+ mActionsContainer.getBoundsOnScreen(mActionsRect);
+ if (!mInteractionStarted) {
+ if (mActionsRect.contains((int) ev2.getRawX(), (int) ev2.getRawY())) {
+ mStartX = ev2.getRawX();
+ mInteractionStarted = true;
+ }
+ } else {
+ float distance = ev2.getRawX() - mStartX;
+ if ((mIsDragging && distance * mTranslationX > 0)
+ || !mActionsRect.contains((int) ev2.getRawX(), (int) ev2.getRawY())
+ || !mActionsContainer.canScrollHorizontally(-1 * (int) distance)) {
+ mIsDragging = true;
+ mTranslationX = distance;
+ mScreenshotStatic.setTranslationX(mTranslationX);
+ return true;
+ } else {
+ mStartX = ev2.getRawX();
+ }
+ }
+ return false;
}
}
@@ -772,23 +845,18 @@ public class ScreenshotView extends FrameLayout implements
ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
float startX = mTranslationX;
float finalX = mDirectionLTR
- ? -1 * (mDismissStartX + mDismissButton.getWidth())
+ ? -1 * (mActionsContainerBackground.getX()
+ + mActionsContainerBackground.getWidth())
: mDisplayMetrics.widthPixels;
anim.addUpdateListener(animation -> {
- float translation = MathUtils.lerp(startX, finalX, animation.getAnimatedFraction());
- mScreenshotPreview.setTranslationX(translation);
- mDismissButton.setX(mDismissStartX + translation);
-
- float yDelta = MathUtils.lerp(0, mDismissDeltaY, animation.getAnimatedFraction());
-
- mActionsContainer.setTranslationY(yDelta);
- mActionsContainerBackground.setTranslationY(yDelta);
+ float translation = MathUtils.lerp(startX, finalX,
+ animation.getAnimatedFraction());
+ mScreenshotStatic.setTranslationX(translation);
setAlpha(1 - animation.getAnimatedFraction());
});
anim.setDuration(400);
-
return anim;
}
@@ -801,15 +869,10 @@ public class ScreenshotView extends FrameLayout implements
anim.addUpdateListener(animation -> {
float translation = MathUtils.lerp(
startX, finalX, animation.getAnimatedFraction());
- mScreenshotPreview.setTranslationX(translation);
- mDismissButton.setX(mDismissStartX + translation);
+ mScreenshotStatic.setTranslationX(translation);
});
return anim;
}
-
- private float dpToPx(float dp) {
- return dp * mDisplayMetrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
- }
}
}