From f2d19a5d0f39f0047aac5d913638cf0b4e830aa6 Mon Sep 17 00:00:00 2001 From: Yuichi Araki Date: Wed, 21 Feb 2024 11:29:30 +0900 Subject: [PATCH] Motion: Update the calculations for predictive back Change-Id: I8ccbc5267ecd3aae1c1179ff5a7036030896ba8a --- .../CheeseArticleFragment.kt | 36 +++++++++++-------- Motion/app/src/main/res/values/dimens.xml | 1 + 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/Motion/app/src/main/java/com/example/android/motion/demo/containertransform/CheeseArticleFragment.kt b/Motion/app/src/main/java/com/example/android/motion/demo/containertransform/CheeseArticleFragment.kt index 9100bb0f..0bb4fae2 100644 --- a/Motion/app/src/main/java/com/example/android/motion/demo/containertransform/CheeseArticleFragment.kt +++ b/Motion/app/src/main/java/com/example/android/motion/demo/containertransform/CheeseArticleFragment.kt @@ -119,37 +119,45 @@ class CheeseArticleFragment : Fragment() { v.findNavController().popBackStack() } + val predictiveBackMargin = resources.getDimensionPixelSize(R.dimen.predictive_back_margin) + var initialTouchY = -1f requireActivity().onBackPressedDispatcher.addCallback( viewLifecycleOwner, object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { // This invokes the sharedElementReturnTransition, which is // MaterialContainerTransform. - // TODO: It pops the scaleX/Y back to 1f. It would look nicer to retain the - // scale. How should we handle it? findNavController().popBackStack() } override fun handleOnBackProgressed(backEvent: BackEventCompat) { val progress = backEvent.progress - // Translate as far as 20% of finger movement. - val translation = progress * background.width * 0.2f - background.translationX = - if (backEvent.swipeEdge == BackEventCompat.EDGE_LEFT) { - translation - } else { - -translation - } - // TODO: Consider handling backEvent.touchY to reflect the vertical movement. - - // Scale down from 100% to 50%. - val scale = (2f - progress) * 0.5f + if (initialTouchY < 0f) { + initialTouchY = backEvent.touchY + } + val progressY = (backEvent.touchY - initialTouchY) / background.height + + // See the motion spec about the calculations below. + // https://developer.android.com/design/ui/mobile/guides/patterns/predictive-back#motion-specs + + // Shift horizontally. + val maxTranslationX = (background.width / 20) - predictiveBackMargin + background.translationX = progress * maxTranslationX * + (if (backEvent.swipeEdge == BackEventCompat.EDGE_LEFT) 1 else -1) + + // Shift vertically. + val maxTranslationY = (background.height / 20) - predictiveBackMargin + background.translationY = progressY * maxTranslationY + + // Scale down from 100% to 90%. + val scale = 1f - (0.1f * progress) background.scaleX = scale background.scaleY = scale } override fun handleOnBackCancelled() { TransitionManager.beginDelayedTransition(background, cancelTransition) + initialTouchY = -1f background.run { translationX = 0f scaleX = 1f diff --git a/Motion/app/src/main/res/values/dimens.xml b/Motion/app/src/main/res/values/dimens.xml index a6158904..ac21ebca 100644 --- a/Motion/app/src/main/res/values/dimens.xml +++ b/Motion/app/src/main/res/values/dimens.xml @@ -21,4 +21,5 @@ 8dp 6dp 24dp + 8dp