Loading packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +27 −49 Original line number Diff line number Diff line Loading @@ -154,7 +154,6 @@ public class ScreenshotController { private SaveImageInBackgroundTask mSaveInBgTask; private Animator mScreenshotAnimation; private Animator mDismissAnimation; private Runnable mOnCompleteRunnable; private boolean mInDarkMode; Loading @@ -168,7 +167,6 @@ public class ScreenshotController { case MESSAGE_CORNER_TIMEOUT: mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_INTERACTION_TIMEOUT); ScreenshotController.this.dismissScreenshot(false); mOnCompleteRunnable.run(); break; default: break; Loading Loading @@ -279,30 +277,22 @@ public class ScreenshotController { rect -> takeScreenshotInternal(finisher, rect)); } boolean isDismissing() { return (mDismissAnimation != null && mDismissAnimation.isRunning()); } /** * Clears current screenshot */ void dismissScreenshot(boolean immediate) { Log.v(TAG, "clearing screenshot"); mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT); mScreenshotView.getViewTreeObserver().removeOnComputeInternalInsetsListener( mScreenshotView); if (!immediate) { mDismissAnimation = mScreenshotView.createScreenshotDismissAnimation(); mDismissAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); clearScreenshot(); // If we're already animating out, don't restart the animation // (but do obey an immediate dismissal) if (!immediate && mScreenshotView.isDismissing()) { Log.v(TAG, "Already dismissing, ignoring duplicate command"); return; } }); mDismissAnimation.start(); Log.v(TAG, "Clearing screenshot"); mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT); if (immediate) { resetScreenshotView(); } else { clearScreenshot(); mScreenshotView.animateDismissal(); } } Loading Loading @@ -373,6 +363,7 @@ public class ScreenshotController { // Inflate the screenshot layout mScreenshotView = (ScreenshotView) LayoutInflater.from(mContext).inflate(R.layout.global_screenshot, null); mScreenshotView.init(mUiEventLogger, this::resetScreenshotView); // TODO(159460485): Remove this when focus is handled properly in the system mScreenshotView.setOnTouchListener((v, event) -> { Loading Loading @@ -438,10 +429,10 @@ public class ScreenshotController { if (mScreenshotView.isAttachedToWindow()) { // if we didn't already dismiss for another reason if (mDismissAnimation == null || !mDismissAnimation.isRunning()) { if (!mScreenshotView.isDismissing()) { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_REENTERED); } dismissScreenshot(true); mScreenshotView.reset(); } mScreenBitmap = screenshot; Loading @@ -459,10 +450,6 @@ public class ScreenshotController { onConfigChanged(mContext.getResources().getConfiguration()); if (mDismissAnimation != null && mDismissAnimation.isRunning()) { mDismissAnimation.cancel(); } // The window is focusable by default setWindowFocusable(true); Loading @@ -474,7 +461,8 @@ public class ScreenshotController { mScrollCaptureClient.request(DEFAULT_DISPLAY, (connection) -> mScreenshotView.showScrollChip(() -> runScrollCapture(connection, () -> dismissScreenshot(true)))); () -> mScreenshotHandler.post( () -> dismissScreenshot(false))))); } } Loading Loading @@ -519,6 +507,7 @@ public class ScreenshotController { */ private void startAnimation(final Consumer<Uri> finisher, Rect screenRect, Insets screenInsets, boolean showFlash) { mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT); mScreenshotHandler.post(() -> { if (!mScreenshotView.isAttachedToWindow()) { mWindowManager.addView(mScreenshotView, mWindowLayoutParams); Loading @@ -531,8 +520,7 @@ public class ScreenshotController { mScreenshotView); mScreenshotAnimation = mScreenshotView.createScreenshotDropInAnimation(screenRect, showFlash, this::onElementTapped); mScreenshotView.createScreenshotDropInAnimation(screenRect, showFlash); saveScreenshotInWorkerThread(finisher, new ScreenshotController.ActionsReadyListener() { Loading @@ -551,6 +539,14 @@ public class ScreenshotController { }); } private void resetScreenshotView() { if (mScreenshotView.isAttachedToWindow()) { mWindowManager.removeView(mScreenshotView); } mScreenshotView.reset(); mOnCompleteRunnable.run(); } /** * Creates a new worker thread and saves the screenshot to the media store. */ Loading Loading @@ -590,7 +586,6 @@ public class ScreenshotController { SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS, AccessibilityManager.FLAG_CONTENT_CONTROLS); mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT); mScreenshotHandler.sendMessageDelayed( mScreenshotHandler.obtainMessage(MESSAGE_CORNER_TIMEOUT), timeoutMs); Loading @@ -602,24 +597,16 @@ public class ScreenshotController { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mScreenshotView.setChipIntents( imageData, event -> onElementTapped(event)); mScreenshotView.setChipIntents(imageData); } }); } else { mScreenshotView.setChipIntents( imageData, this::onElementTapped); mScreenshotView.setChipIntents(imageData); } }); } } private void onElementTapped(ScreenshotEvent event) { mUiEventLogger.log(event); dismissScreenshot(false); mOnCompleteRunnable.run(); } /** * Logs success/failure of the screenshot saving task, and shows an error if it failed. */ Loading @@ -633,20 +620,11 @@ public class ScreenshotController { } } private void clearScreenshot() { if (mScreenshotView.isAttachedToWindow()) { mWindowManager.removeView(mScreenshotView); } mScreenshotView.reset(); } private boolean isUserSetupComplete() { return Settings.Secure.getInt(mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1; } /** * Updates the window focusability. If the window is already showing, then it updates the * window immediately, otherwise the layout params will be applied when the window is next Loading packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java +91 −35 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; import com.android.systemui.shared.system.QuickStepContract; Loading Loading @@ -115,6 +116,10 @@ public class ScreenshotView extends FrameLayout implements private ScreenshotActionChip mEditChip; private ScreenshotActionChip mScrollChip; private UiEventLogger mUiEventLogger; private Runnable mOnDismissRunnable; private Animator mDismissAnimation; private final ArrayList<ScreenshotActionChip> mSmartChips = new ArrayList<>(); private PendingInteraction mPendingInteraction; Loading Loading @@ -248,6 +253,17 @@ public class ScreenshotView extends FrameLayout implements requestFocus(); } /** * Set up the logger and callback on dismissal. * * Note: must be called before any other (non-constructor) method or null pointer exceptions * may occur. */ void init(UiEventLogger uiEventLogger, Runnable onDismissRunnable) { mUiEventLogger = uiEventLogger; mOnDismissRunnable = onDismissRunnable; } void takePartialScreenshot(Consumer<Rect> onPartialScreenshotSelected) { mScreenshotSelectorView.setOnScreenshotSelected(onPartialScreenshotSelected); mScreenshotSelectorView.setVisibility(View.VISIBLE); Loading @@ -260,8 +276,7 @@ public class ScreenshotView extends FrameLayout implements mScreenshotPreview.setVisibility(View.INVISIBLE); } AnimatorSet createScreenshotDropInAnimation(Rect bounds, boolean showFlash, Consumer<ScreenshotEvent> onElementTapped) { AnimatorSet createScreenshotDropInAnimation(Rect bounds, boolean showFlash) { mScreenshotPreview.setLayerType(View.LAYER_TYPE_HARDWARE, null); mScreenshotPreview.buildLayer(); Loading Loading @@ -362,8 +377,10 @@ public class ScreenshotView extends FrameLayout implements @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mDismissButton.setOnClickListener(view -> onElementTapped.accept(ScreenshotEvent.SCREENSHOT_EXPLICIT_DISMISSAL)); mDismissButton.setOnClickListener(view -> { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EXPLICIT_DISMISSAL); animateDismissal(); }); mDismissButton.setAlpha(1); float dismissOffset = mDismissButton.getWidth() / 2f; float finalDismissX = mDirectionLTR Loading Loading @@ -460,19 +477,25 @@ public class ScreenshotView extends FrameLayout implements return animator; } void setChipIntents(ScreenshotController.SavedImageData imageData, Consumer<ScreenshotEvent> onElementTapped) { void setChipIntents(ScreenshotController.SavedImageData imageData) { mShareChip.setPendingIntent(imageData.shareAction.actionIntent, () -> onElementTapped.accept(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED)); () -> { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED); animateDismissal(); }); mEditChip.setPendingIntent(imageData.editAction.actionIntent, () -> onElementTapped.accept(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED)); () -> { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED); animateDismissal(); }); mScreenshotPreview.setOnClickListener(v -> { try { imageData.editAction.actionIntent.send(); } catch (PendingIntent.CanceledException e) { Log.e(TAG, "Intent cancelled", e); } onElementTapped.accept(ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED); mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED); animateDismissal(); }); if (mPendingInteraction != null) { Loading @@ -496,43 +519,49 @@ public class ScreenshotView extends FrameLayout implements actionChip.setText(smartAction.title); actionChip.setIcon(smartAction.getIcon(), false); actionChip.setPendingIntent(smartAction.actionIntent, () -> onElementTapped.accept( ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED)); () -> { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED); animateDismissal(); }); mActionsView.addView(actionChip); mSmartChips.add(actionChip); } } } boolean isDismissing() { return (mDismissAnimation != null && mDismissAnimation.isRunning()); } AnimatorSet createScreenshotDismissAnimation() { ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1); alphaAnim.setStartDelay(SCREENSHOT_DISMISS_ALPHA_OFFSET_MS); alphaAnim.setDuration(SCREENSHOT_DISMISS_ALPHA_DURATION_MS); alphaAnim.addUpdateListener(animation -> { setAlpha(1 - animation.getAnimatedFraction()); }); ValueAnimator yAnim = ValueAnimator.ofFloat(0, 1); yAnim.setInterpolator(mAccelerateInterpolator); yAnim.setDuration(SCREENSHOT_DISMISS_Y_DURATION_MS); float screenshotStartY = mScreenshotPreview.getTranslationY(); float dismissStartY = mDismissButton.getTranslationY(); yAnim.addUpdateListener(animation -> { float yDelta = MathUtils.lerp(0, mDismissDeltaY, animation.getAnimatedFraction()); mScreenshotPreview.setTranslationY(screenshotStartY + yDelta); mDismissButton.setTranslationY(dismissStartY + yDelta); mActionsContainer.setTranslationY(yDelta); mActionsContainerBackground.setTranslationY(yDelta); }); void animateDismissal() { getViewTreeObserver().removeOnComputeInternalInsetsListener(this); mDismissAnimation = createScreenshotDismissAnimation(); mDismissAnimation.addListener(new AnimatorListenerAdapter() { private boolean mCancelled = false; AnimatorSet animSet = new AnimatorSet(); animSet.play(yAnim).with(alphaAnim); @Override public void onAnimationCancel(Animator animation) { super.onAnimationCancel(animation); mCancelled = true; } return animSet; @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); if (!mCancelled) { mOnDismissRunnable.run(); } } }); mDismissAnimation.start(); } void reset() { if (mDismissAnimation != null && mDismissAnimation.isRunning()) { mDismissAnimation.cancel(); } // Make sure we clean up the view tree observer getViewTreeObserver().removeOnComputeInternalInsetsListener(this); // Clear any references to the bitmap mScreenshotPreview.setImageDrawable(null); mActionsContainerBackground.setVisibility(View.GONE); Loading Loading @@ -561,6 +590,33 @@ public class ScreenshotView extends FrameLayout implements mScreenshotSelectorView.stop(); } private AnimatorSet createScreenshotDismissAnimation() { ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1); alphaAnim.setStartDelay(SCREENSHOT_DISMISS_ALPHA_OFFSET_MS); alphaAnim.setDuration(SCREENSHOT_DISMISS_ALPHA_DURATION_MS); alphaAnim.addUpdateListener(animation -> { setAlpha(1 - animation.getAnimatedFraction()); }); ValueAnimator yAnim = ValueAnimator.ofFloat(0, 1); yAnim.setInterpolator(mAccelerateInterpolator); yAnim.setDuration(SCREENSHOT_DISMISS_Y_DURATION_MS); float screenshotStartY = mScreenshotPreview.getTranslationY(); float dismissStartY = mDismissButton.getTranslationY(); yAnim.addUpdateListener(animation -> { float yDelta = MathUtils.lerp(0, mDismissDeltaY, animation.getAnimatedFraction()); mScreenshotPreview.setTranslationY(screenshotStartY + yDelta); mDismissButton.setTranslationY(dismissStartY + yDelta); mActionsContainer.setTranslationY(yDelta); mActionsContainerBackground.setTranslationY(yDelta); }); AnimatorSet animSet = new AnimatorSet(); animSet.play(yAnim).with(alphaAnim); return animSet; } /** * Create a drawable using the size of the bitmap and insets as the fractional inset parameters. */ Loading packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java +1 −1 Original line number Diff line number Diff line Loading @@ -144,7 +144,7 @@ public class TakeScreenshotService extends Service { @Override public boolean onUnbind(Intent intent) { if (mScreenshot != null && !mScreenshot.isDismissing()) { if (mScreenshot != null) { mScreenshot.dismissScreenshot(true); } unregisterReceiver(mBroadcastReceiver); Loading Loading
packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +27 −49 Original line number Diff line number Diff line Loading @@ -154,7 +154,6 @@ public class ScreenshotController { private SaveImageInBackgroundTask mSaveInBgTask; private Animator mScreenshotAnimation; private Animator mDismissAnimation; private Runnable mOnCompleteRunnable; private boolean mInDarkMode; Loading @@ -168,7 +167,6 @@ public class ScreenshotController { case MESSAGE_CORNER_TIMEOUT: mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_INTERACTION_TIMEOUT); ScreenshotController.this.dismissScreenshot(false); mOnCompleteRunnable.run(); break; default: break; Loading Loading @@ -279,30 +277,22 @@ public class ScreenshotController { rect -> takeScreenshotInternal(finisher, rect)); } boolean isDismissing() { return (mDismissAnimation != null && mDismissAnimation.isRunning()); } /** * Clears current screenshot */ void dismissScreenshot(boolean immediate) { Log.v(TAG, "clearing screenshot"); mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT); mScreenshotView.getViewTreeObserver().removeOnComputeInternalInsetsListener( mScreenshotView); if (!immediate) { mDismissAnimation = mScreenshotView.createScreenshotDismissAnimation(); mDismissAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); clearScreenshot(); // If we're already animating out, don't restart the animation // (but do obey an immediate dismissal) if (!immediate && mScreenshotView.isDismissing()) { Log.v(TAG, "Already dismissing, ignoring duplicate command"); return; } }); mDismissAnimation.start(); Log.v(TAG, "Clearing screenshot"); mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT); if (immediate) { resetScreenshotView(); } else { clearScreenshot(); mScreenshotView.animateDismissal(); } } Loading Loading @@ -373,6 +363,7 @@ public class ScreenshotController { // Inflate the screenshot layout mScreenshotView = (ScreenshotView) LayoutInflater.from(mContext).inflate(R.layout.global_screenshot, null); mScreenshotView.init(mUiEventLogger, this::resetScreenshotView); // TODO(159460485): Remove this when focus is handled properly in the system mScreenshotView.setOnTouchListener((v, event) -> { Loading Loading @@ -438,10 +429,10 @@ public class ScreenshotController { if (mScreenshotView.isAttachedToWindow()) { // if we didn't already dismiss for another reason if (mDismissAnimation == null || !mDismissAnimation.isRunning()) { if (!mScreenshotView.isDismissing()) { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_REENTERED); } dismissScreenshot(true); mScreenshotView.reset(); } mScreenBitmap = screenshot; Loading @@ -459,10 +450,6 @@ public class ScreenshotController { onConfigChanged(mContext.getResources().getConfiguration()); if (mDismissAnimation != null && mDismissAnimation.isRunning()) { mDismissAnimation.cancel(); } // The window is focusable by default setWindowFocusable(true); Loading @@ -474,7 +461,8 @@ public class ScreenshotController { mScrollCaptureClient.request(DEFAULT_DISPLAY, (connection) -> mScreenshotView.showScrollChip(() -> runScrollCapture(connection, () -> dismissScreenshot(true)))); () -> mScreenshotHandler.post( () -> dismissScreenshot(false))))); } } Loading Loading @@ -519,6 +507,7 @@ public class ScreenshotController { */ private void startAnimation(final Consumer<Uri> finisher, Rect screenRect, Insets screenInsets, boolean showFlash) { mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT); mScreenshotHandler.post(() -> { if (!mScreenshotView.isAttachedToWindow()) { mWindowManager.addView(mScreenshotView, mWindowLayoutParams); Loading @@ -531,8 +520,7 @@ public class ScreenshotController { mScreenshotView); mScreenshotAnimation = mScreenshotView.createScreenshotDropInAnimation(screenRect, showFlash, this::onElementTapped); mScreenshotView.createScreenshotDropInAnimation(screenRect, showFlash); saveScreenshotInWorkerThread(finisher, new ScreenshotController.ActionsReadyListener() { Loading @@ -551,6 +539,14 @@ public class ScreenshotController { }); } private void resetScreenshotView() { if (mScreenshotView.isAttachedToWindow()) { mWindowManager.removeView(mScreenshotView); } mScreenshotView.reset(); mOnCompleteRunnable.run(); } /** * Creates a new worker thread and saves the screenshot to the media store. */ Loading Loading @@ -590,7 +586,6 @@ public class ScreenshotController { SCREENSHOT_CORNER_DEFAULT_TIMEOUT_MILLIS, AccessibilityManager.FLAG_CONTENT_CONTROLS); mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT); mScreenshotHandler.sendMessageDelayed( mScreenshotHandler.obtainMessage(MESSAGE_CORNER_TIMEOUT), timeoutMs); Loading @@ -602,24 +597,16 @@ public class ScreenshotController { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mScreenshotView.setChipIntents( imageData, event -> onElementTapped(event)); mScreenshotView.setChipIntents(imageData); } }); } else { mScreenshotView.setChipIntents( imageData, this::onElementTapped); mScreenshotView.setChipIntents(imageData); } }); } } private void onElementTapped(ScreenshotEvent event) { mUiEventLogger.log(event); dismissScreenshot(false); mOnCompleteRunnable.run(); } /** * Logs success/failure of the screenshot saving task, and shows an error if it failed. */ Loading @@ -633,20 +620,11 @@ public class ScreenshotController { } } private void clearScreenshot() { if (mScreenshotView.isAttachedToWindow()) { mWindowManager.removeView(mScreenshotView); } mScreenshotView.reset(); } private boolean isUserSetupComplete() { return Settings.Secure.getInt(mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1; } /** * Updates the window focusability. If the window is already showing, then it updates the * window immediately, otherwise the layout params will be applied when the window is next Loading
packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java +91 −35 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; import com.android.systemui.shared.system.QuickStepContract; Loading Loading @@ -115,6 +116,10 @@ public class ScreenshotView extends FrameLayout implements private ScreenshotActionChip mEditChip; private ScreenshotActionChip mScrollChip; private UiEventLogger mUiEventLogger; private Runnable mOnDismissRunnable; private Animator mDismissAnimation; private final ArrayList<ScreenshotActionChip> mSmartChips = new ArrayList<>(); private PendingInteraction mPendingInteraction; Loading Loading @@ -248,6 +253,17 @@ public class ScreenshotView extends FrameLayout implements requestFocus(); } /** * Set up the logger and callback on dismissal. * * Note: must be called before any other (non-constructor) method or null pointer exceptions * may occur. */ void init(UiEventLogger uiEventLogger, Runnable onDismissRunnable) { mUiEventLogger = uiEventLogger; mOnDismissRunnable = onDismissRunnable; } void takePartialScreenshot(Consumer<Rect> onPartialScreenshotSelected) { mScreenshotSelectorView.setOnScreenshotSelected(onPartialScreenshotSelected); mScreenshotSelectorView.setVisibility(View.VISIBLE); Loading @@ -260,8 +276,7 @@ public class ScreenshotView extends FrameLayout implements mScreenshotPreview.setVisibility(View.INVISIBLE); } AnimatorSet createScreenshotDropInAnimation(Rect bounds, boolean showFlash, Consumer<ScreenshotEvent> onElementTapped) { AnimatorSet createScreenshotDropInAnimation(Rect bounds, boolean showFlash) { mScreenshotPreview.setLayerType(View.LAYER_TYPE_HARDWARE, null); mScreenshotPreview.buildLayer(); Loading Loading @@ -362,8 +377,10 @@ public class ScreenshotView extends FrameLayout implements @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mDismissButton.setOnClickListener(view -> onElementTapped.accept(ScreenshotEvent.SCREENSHOT_EXPLICIT_DISMISSAL)); mDismissButton.setOnClickListener(view -> { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EXPLICIT_DISMISSAL); animateDismissal(); }); mDismissButton.setAlpha(1); float dismissOffset = mDismissButton.getWidth() / 2f; float finalDismissX = mDirectionLTR Loading Loading @@ -460,19 +477,25 @@ public class ScreenshotView extends FrameLayout implements return animator; } void setChipIntents(ScreenshotController.SavedImageData imageData, Consumer<ScreenshotEvent> onElementTapped) { void setChipIntents(ScreenshotController.SavedImageData imageData) { mShareChip.setPendingIntent(imageData.shareAction.actionIntent, () -> onElementTapped.accept(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED)); () -> { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED); animateDismissal(); }); mEditChip.setPendingIntent(imageData.editAction.actionIntent, () -> onElementTapped.accept(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED)); () -> { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED); animateDismissal(); }); mScreenshotPreview.setOnClickListener(v -> { try { imageData.editAction.actionIntent.send(); } catch (PendingIntent.CanceledException e) { Log.e(TAG, "Intent cancelled", e); } onElementTapped.accept(ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED); mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED); animateDismissal(); }); if (mPendingInteraction != null) { Loading @@ -496,43 +519,49 @@ public class ScreenshotView extends FrameLayout implements actionChip.setText(smartAction.title); actionChip.setIcon(smartAction.getIcon(), false); actionChip.setPendingIntent(smartAction.actionIntent, () -> onElementTapped.accept( ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED)); () -> { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED); animateDismissal(); }); mActionsView.addView(actionChip); mSmartChips.add(actionChip); } } } boolean isDismissing() { return (mDismissAnimation != null && mDismissAnimation.isRunning()); } AnimatorSet createScreenshotDismissAnimation() { ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1); alphaAnim.setStartDelay(SCREENSHOT_DISMISS_ALPHA_OFFSET_MS); alphaAnim.setDuration(SCREENSHOT_DISMISS_ALPHA_DURATION_MS); alphaAnim.addUpdateListener(animation -> { setAlpha(1 - animation.getAnimatedFraction()); }); ValueAnimator yAnim = ValueAnimator.ofFloat(0, 1); yAnim.setInterpolator(mAccelerateInterpolator); yAnim.setDuration(SCREENSHOT_DISMISS_Y_DURATION_MS); float screenshotStartY = mScreenshotPreview.getTranslationY(); float dismissStartY = mDismissButton.getTranslationY(); yAnim.addUpdateListener(animation -> { float yDelta = MathUtils.lerp(0, mDismissDeltaY, animation.getAnimatedFraction()); mScreenshotPreview.setTranslationY(screenshotStartY + yDelta); mDismissButton.setTranslationY(dismissStartY + yDelta); mActionsContainer.setTranslationY(yDelta); mActionsContainerBackground.setTranslationY(yDelta); }); void animateDismissal() { getViewTreeObserver().removeOnComputeInternalInsetsListener(this); mDismissAnimation = createScreenshotDismissAnimation(); mDismissAnimation.addListener(new AnimatorListenerAdapter() { private boolean mCancelled = false; AnimatorSet animSet = new AnimatorSet(); animSet.play(yAnim).with(alphaAnim); @Override public void onAnimationCancel(Animator animation) { super.onAnimationCancel(animation); mCancelled = true; } return animSet; @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); if (!mCancelled) { mOnDismissRunnable.run(); } } }); mDismissAnimation.start(); } void reset() { if (mDismissAnimation != null && mDismissAnimation.isRunning()) { mDismissAnimation.cancel(); } // Make sure we clean up the view tree observer getViewTreeObserver().removeOnComputeInternalInsetsListener(this); // Clear any references to the bitmap mScreenshotPreview.setImageDrawable(null); mActionsContainerBackground.setVisibility(View.GONE); Loading Loading @@ -561,6 +590,33 @@ public class ScreenshotView extends FrameLayout implements mScreenshotSelectorView.stop(); } private AnimatorSet createScreenshotDismissAnimation() { ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1); alphaAnim.setStartDelay(SCREENSHOT_DISMISS_ALPHA_OFFSET_MS); alphaAnim.setDuration(SCREENSHOT_DISMISS_ALPHA_DURATION_MS); alphaAnim.addUpdateListener(animation -> { setAlpha(1 - animation.getAnimatedFraction()); }); ValueAnimator yAnim = ValueAnimator.ofFloat(0, 1); yAnim.setInterpolator(mAccelerateInterpolator); yAnim.setDuration(SCREENSHOT_DISMISS_Y_DURATION_MS); float screenshotStartY = mScreenshotPreview.getTranslationY(); float dismissStartY = mDismissButton.getTranslationY(); yAnim.addUpdateListener(animation -> { float yDelta = MathUtils.lerp(0, mDismissDeltaY, animation.getAnimatedFraction()); mScreenshotPreview.setTranslationY(screenshotStartY + yDelta); mDismissButton.setTranslationY(dismissStartY + yDelta); mActionsContainer.setTranslationY(yDelta); mActionsContainerBackground.setTranslationY(yDelta); }); AnimatorSet animSet = new AnimatorSet(); animSet.play(yAnim).with(alphaAnim); return animSet; } /** * Create a drawable using the size of the bitmap and insets as the fractional inset parameters. */ Loading
packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java +1 −1 Original line number Diff line number Diff line Loading @@ -144,7 +144,7 @@ public class TakeScreenshotService extends Service { @Override public boolean onUnbind(Intent intent) { if (mScreenshot != null && !mScreenshot.isDismissing()) { if (mScreenshot != null) { mScreenshot.dismissScreenshot(true); } unregisterReceiver(mBroadcastReceiver); Loading