diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index a58f930df..4c5f01cd4 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -168,7 +168,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session swipeRefresh = WeakReference(swipeRefresh), arguments = arguments!! ).apply { - beginAnimationIfNecessary() + beginAnimateInIfNecessary() } return getSessionById()?.also { session -> diff --git a/app/src/main/java/org/mozilla/fenix/browser/BrowserAnimator.kt b/app/src/main/java/org/mozilla/fenix/browser/BrowserAnimator.kt index 5b7e6b019..74c4224db 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BrowserAnimator.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BrowserAnimator.kt @@ -41,17 +41,34 @@ class BrowserAnimator( private val unwrappedSwipeRefresh: View? get() = swipeRefresh.get() + private val browserInValueAnimator = ValueAnimator.ofFloat(0f, END_ANIMATOR_VALUE).apply { + addUpdateListener { + unwrappedSwipeRefresh?.scaleX = STARTING_XY_SCALE + XY_SCALE_MULTIPLIER * it.animatedFraction + unwrappedSwipeRefresh?.scaleY = STARTING_XY_SCALE + XY_SCALE_MULTIPLIER * it.animatedFraction + unwrappedSwipeRefresh?.alpha = it.animatedFraction + } + + doOnEnd { + unwrappedEngineView?.asView()?.visibility = View.VISIBLE + unwrappedSwipeRefresh?.background = null + arguments.putBoolean(SHOULD_ANIMATE_FLAG, false) + } + + interpolator = DecelerateInterpolator() + duration = ANIMATION_DURATION + } + /** - * Triggers the browser animation to run if necessary (based on the SHOULD_ANIMATE_FLAG). Also + * Triggers the *in* browser animation to run if necessary (based on the SHOULD_ANIMATE_FLAG). Also * removes the flag from the bundle so it is not played on future entries into the fragment. */ - fun beginAnimationIfNecessary() { + fun beginAnimateInIfNecessary() { val shouldAnimate = arguments.getBoolean(SHOULD_ANIMATE_FLAG, false) if (shouldAnimate) { viewLifeCycleScope?.launch(Dispatchers.Main) { delay(ANIMATION_DELAY) captureEngineViewAndDrawStatically { - animateBrowserEngine(unwrappedSwipeRefresh) + browserInValueAnimator.start() } } } else { @@ -62,26 +79,15 @@ class BrowserAnimator( } /** - * Details exactly how the browserEngine animation should look and plays it. + * Triggers the *out* browser animation to run. */ - private fun animateBrowserEngine(browserEngine: View?) { - val valueAnimator = ValueAnimator.ofFloat(0f, END_ANIMATOR_VALUE) - - valueAnimator.addUpdateListener { - browserEngine?.scaleX = STARTING_XY_SCALE + XY_SCALE_MULTIPLIER * it.animatedFraction - browserEngine?.scaleY = STARTING_XY_SCALE + XY_SCALE_MULTIPLIER * it.animatedFraction - browserEngine?.alpha = it.animatedFraction + fun beginAnimateOut() { + viewLifeCycleScope?.launch(Dispatchers.Main) { + captureEngineViewAndDrawStatically { + unwrappedEngineView?.asView()?.visibility = View.GONE + browserInValueAnimator.reverse() + } } - - valueAnimator.doOnEnd { - unwrappedEngineView?.asView()?.visibility = View.VISIBLE - unwrappedSwipeRefresh?.background = null - arguments.putBoolean(SHOULD_ANIMATE_FLAG, false) - } - - valueAnimator.interpolator = DecelerateInterpolator() - valueAnimator.duration = ANIMATION_DURATION - valueAnimator.start() } /** diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt index ca464be31..074418199 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarController.kt @@ -14,6 +14,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.MainScope +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager @@ -300,7 +301,11 @@ class DefaultBrowserToolbarController( } private fun animateTabAndNavigateHome() { - browserAnimator.captureEngineViewAndDrawStatically { + scope.launch { + browserAnimator.beginAnimateOut() + // Delay for a short amount of time so the browser has time to start animating out + // before we transition the fragment. This makes the animation feel smoother + delay(ANIMATION_DELAY) if (!navController.popBackStack(R.id.homeFragment, false)) { val directions = BrowserFragmentDirections.actionBrowserFragmentToHomeFragment() navController.nav( @@ -356,8 +361,7 @@ class DefaultBrowserToolbarController( } companion object { - @VisibleForTesting - const val TAB_ITEM_TRANSITION_NAME = "tab_item" + const val ANIMATION_DELAY = 50L internal const val TELEMETRY_BROWSER_IDENTIFIER = "browserMenu" } } diff --git a/app/src/main/res/anim/zoom_out_fade.xml b/app/src/main/res/anim/zoom_out_fade.xml new file mode 100644 index 000000000..720b5bf3c --- /dev/null +++ b/app/src/main/res/anim/zoom_out_fade.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 4a9431c33..153eee267 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -58,6 +58,7 @@ + app:popEnterAnim="@anim/zoom_out_fade" />