Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cb9c41e8 authored by Miranda Kephart's avatar Miranda Kephart Committed by Matt Casey
Browse files

Fix back gesture/dismiss button in screenshot shelf UI

Bug: 334877806
Bug: 329659738
Test: manual (testing back gesture/touch interaction)
Flag: ACONFIG com.android.systemui.screenshot_shelf_ui DEVELOPMENT

Change-Id: I01ff75588b01bb34428d3cffa3ce5f0712bb7f72
Merged-In: I01ff75588b01bb34428d3cffa3ce5f0712bb7f72
parent b0255c0e
Loading
Loading
Loading
Loading
+9 −18
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@ import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_DISMISSED_OTHE
import com.android.systemui.screenshot.scroll.ScrollCaptureController
import com.android.systemui.screenshot.ui.ScreenshotAnimationController
import com.android.systemui.screenshot.ui.ScreenshotShelfView
import com.android.systemui.screenshot.ui.SwipeGestureListener
import com.android.systemui.screenshot.ui.binder.ScreenshotShelfViewBinder
import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel
import dagger.assisted.Assisted
@@ -76,17 +75,15 @@ constructor(
    override var isPendingSharedTransition = false

    private val animationController = ScreenshotAnimationController(view)
    private val swipeGestureListener =
        SwipeGestureListener(
            view,
            onDismiss = { requestDismissal(ScreenshotEvent.SCREENSHOT_SWIPE_DISMISSED, it) },
            onCancel = { animationController.getSwipeReturnAnimation().start() }
        )

    init {
        ScreenshotShelfViewBinder.bind(view, viewModel, LayoutInflater.from(context)) {
            swipeGestureListener.onMotionEvent(it)
        }
        ScreenshotShelfViewBinder.bind(
            view,
            viewModel,
            LayoutInflater.from(context),
            onDismissalRequested = { event, velocity -> requestDismissal(event, velocity) },
            onDismissalCancelled = { animationController.getSwipeReturnAnimation().start() }
        )
        addPredictiveBackListener { requestDismissal(SCREENSHOT_DISMISSED_OTHER) }
        setOnKeyListener { requestDismissal(SCREENSHOT_DISMISSED_OTHER) }
        debugLog(DEBUG_WINDOW) { "adding OnComputeInternalInsetsListener" }
@@ -120,10 +117,10 @@ constructor(
    override fun setChipIntents(imageData: SavedImageData) {}

    override fun requestDismissal(event: ScreenshotEvent?) {
        requestDismissal(event, getDismissalVelocity())
        requestDismissal(event, null)
    }

    private fun requestDismissal(event: ScreenshotEvent?, velocity: Float) {
    private fun requestDismissal(event: ScreenshotEvent?, velocity: Float?) {
        debugLog(DEBUG_DISMISS) { "screenshot dismissal requested: $event" }

        // If we're already animating out, don't restart the animation
@@ -235,12 +232,6 @@ constructor(
        )
    }

    private fun getDismissalVelocity(): Float {
        val isLTR = view.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_LTR
        // dismiss to the left in LTR locales, to the right in RTL
        return if (isLTR) -1.5f else 1.5f
    }

    @AssistedFactory
    interface Factory : ScreenshotViewProxy.Factory {
        override fun getProxy(context: Context, displayId: Int): ScreenshotShelfViewProxy
+18 −1
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.animation.ValueAnimator
import android.view.View
import com.android.systemui.res.R
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.sign

class ScreenshotAnimationController(private val view: ScreenshotShelfView) {
    private var animator: Animator? = null
@@ -52,7 +54,8 @@ class ScreenshotAnimationController(private val view: ScreenshotShelfView) {
        return animator
    }

    fun getSwipeDismissAnimation(velocity: Float): Animator {
    fun getSwipeDismissAnimation(requestedVelocity: Float?): Animator {
        val velocity = getAdjustedVelocity(requestedVelocity)
        val screenWidth = view.resources.displayMetrics.widthPixels
        // translation at which point the visible UI is fully off the screen (in the direction
        // according to velocity)
@@ -77,4 +80,18 @@ class ScreenshotAnimationController(private val view: ScreenshotShelfView) {
    fun cancel() {
        animator?.cancel()
    }

    private fun getAdjustedVelocity(requestedVelocity: Float?): Float {
        return if (requestedVelocity == null) {
            val isLTR = view.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_LTR
            // dismiss to the left in LTR locales, to the right in RTL
            if (isLTR) -1 * MINIMUM_VELOCITY else MINIMUM_VELOCITY
        } else {
            sign(requestedVelocity) * max(MINIMUM_VELOCITY, abs(requestedVelocity))
        }
    }

    companion object {
        private const val MINIMUM_VELOCITY = 1.5f // pixels per second
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ class ScreenshotShelfView(context: Context, attrs: AttributeSet? = null) :

    override fun onFinishInflate() {
        super.onFinishInflate()
        // Get focus so that the key events go to the layout.
        isFocusableInTouchMode = true
        screenshotPreview = requireViewById(R.id.screenshot_preview)
        actionsContainerBackground = requireViewById(R.id.actions_container_background)
        dismissButton = requireViewById(R.id.screenshot_dismiss_button)
+1 −2
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import android.view.VelocityTracker
import android.view.View
import com.android.systemui.screenshot.FloatingWindowUtil
import kotlin.math.abs
import kotlin.math.sign

class SwipeGestureListener(
    private val view: View,
@@ -52,7 +51,7 @@ class SwipeGestureListener(
                    abs(view.translationX) >
                        FloatingWindowUtil.dpToPx(displayMetrics, DISMISS_THRESHOLD_DP)
                ) {
                    onDismiss.invoke(1.5f * sign(view.translationX))
                    onDismiss.invoke(xVelocity)
                    return true
                } else {
                    velocityTracker.clear()
+18 −5
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.systemui.screenshot.ui.binder

import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
@@ -26,7 +25,9 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.res.R
import com.android.systemui.screenshot.ScreenshotEvent
import com.android.systemui.screenshot.ui.ScreenshotShelfView
import com.android.systemui.screenshot.ui.SwipeGestureListener
import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel
import com.android.systemui.util.children
import kotlinx.coroutines.launch
@@ -36,16 +37,28 @@ object ScreenshotShelfViewBinder {
        view: ScreenshotShelfView,
        viewModel: ScreenshotViewModel,
        layoutInflater: LayoutInflater,
        onTouchListener: (MotionEvent) -> Boolean,
        onDismissalRequested: (event: ScreenshotEvent, velocity: Float?) -> Unit,
        onDismissalCancelled: () -> Unit,
    ) {
        view.onTouchInterceptListener = onTouchListener
        val swipeGestureListener =
            SwipeGestureListener(
                view,
                onDismiss = {
                    onDismissalRequested(ScreenshotEvent.SCREENSHOT_SWIPE_DISMISSED, it)
                },
                onCancel = onDismissalCancelled
            )
        view.onTouchInterceptListener = { swipeGestureListener.onMotionEvent(it) }

        val previewView: ImageView = view.requireViewById(R.id.screenshot_preview)
        val previewBorder = view.requireViewById<View>(R.id.screenshot_preview_border)
        previewView.clipToOutline = true
        val actionsContainer: LinearLayout = view.requireViewById(R.id.screenshot_actions)
        view.requireViewById<View>(R.id.screenshot_dismiss_button).visibility =
            if (viewModel.showDismissButton) View.VISIBLE else View.GONE
        val dismissButton = view.requireViewById<View>(R.id.screenshot_dismiss_button)
        dismissButton.visibility = if (viewModel.showDismissButton) View.VISIBLE else View.GONE
        dismissButton.setOnClickListener {
            onDismissalRequested(ScreenshotEvent.SCREENSHOT_EXPLICIT_DISMISSAL, null)
        }

        view.repeatWhenAttached {
            lifecycleScope.launch {