1
0
Fork 0

For #167: Adds browser -> home animation

master
Sawyer Blatz 2020-03-02 14:13:13 -08:00
parent b717926f72
commit 8e06933e8d
5 changed files with 56 additions and 26 deletions

View File

@ -168,7 +168,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
swipeRefresh = WeakReference(swipeRefresh), swipeRefresh = WeakReference(swipeRefresh),
arguments = arguments!! arguments = arguments!!
).apply { ).apply {
beginAnimationIfNecessary() beginAnimateInIfNecessary()
} }
return getSessionById()?.also { session -> return getSessionById()?.also { session ->

View File

@ -41,17 +41,34 @@ class BrowserAnimator(
private val unwrappedSwipeRefresh: View? private val unwrappedSwipeRefresh: View?
get() = swipeRefresh.get() 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. * 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) val shouldAnimate = arguments.getBoolean(SHOULD_ANIMATE_FLAG, false)
if (shouldAnimate) { if (shouldAnimate) {
viewLifeCycleScope?.launch(Dispatchers.Main) { viewLifeCycleScope?.launch(Dispatchers.Main) {
delay(ANIMATION_DELAY) delay(ANIMATION_DELAY)
captureEngineViewAndDrawStatically { captureEngineViewAndDrawStatically {
animateBrowserEngine(unwrappedSwipeRefresh) browserInValueAnimator.start()
} }
} }
} else { } 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?) { fun beginAnimateOut() {
val valueAnimator = ValueAnimator.ofFloat(0f, END_ANIMATOR_VALUE) viewLifeCycleScope?.launch(Dispatchers.Main) {
captureEngineViewAndDrawStatically {
valueAnimator.addUpdateListener { unwrappedEngineView?.asView()?.visibility = View.GONE
browserEngine?.scaleX = STARTING_XY_SCALE + XY_SCALE_MULTIPLIER * it.animatedFraction browserInValueAnimator.reverse()
browserEngine?.scaleY = STARTING_XY_SCALE + XY_SCALE_MULTIPLIER * it.animatedFraction }
browserEngine?.alpha = it.animatedFraction
} }
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()
} }
/** /**

View File

@ -14,6 +14,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import mozilla.components.browser.session.Session import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager import mozilla.components.browser.session.SessionManager
@ -300,7 +301,11 @@ class DefaultBrowserToolbarController(
} }
private fun animateTabAndNavigateHome() { 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)) { if (!navController.popBackStack(R.id.homeFragment, false)) {
val directions = BrowserFragmentDirections.actionBrowserFragmentToHomeFragment() val directions = BrowserFragmentDirections.actionBrowserFragmentToHomeFragment()
navController.nav( navController.nav(
@ -356,8 +361,7 @@ class DefaultBrowserToolbarController(
} }
companion object { companion object {
@VisibleForTesting const val ANIMATION_DELAY = 50L
const val TAB_ITEM_TRANSITION_NAME = "tab_item"
internal const val TELEMETRY_BROWSER_IDENTIFIER = "browserMenu" internal const val TELEMETRY_BROWSER_IDENTIFIER = "browserMenu"
} }
} }

View File

@ -0,0 +1,19 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:interpolator="@android:interpolator/decelerate_cubic"
android:fromAlpha="0" android:toAlpha="1"
android:duration="175" />
<scale
android:interpolator="@android:interpolator/decelerate_cubic"
android:pivotX="50%"
android:pivotY="50%"
android:fromXScale="108%"
android:toXScale="100%"
android:fromYScale="108%"
android:toYScale="100%"
android:duration="175" />
</set>

View File

@ -58,6 +58,7 @@
<fragment <fragment
android:id="@+id/homeFragment" android:id="@+id/homeFragment"
android:name="org.mozilla.fenix.home.HomeFragment" android:name="org.mozilla.fenix.home.HomeFragment"
app:enterAnim="@anim/zoom_out_fade"
tools:layout="@layout/fragment_home"> tools:layout="@layout/fragment_home">
<action <action
android:id="@+id/action_homeFragment_to_turnOnSyncFragment" android:id="@+id/action_homeFragment_to_turnOnSyncFragment"
@ -76,7 +77,7 @@
android:id="@+id/action_homeFragment_to_browserFragment" android:id="@+id/action_homeFragment_to_browserFragment"
app:destination="@id/browserFragment" app:destination="@id/browserFragment"
app:exitAnim="@anim/zoom_in_fade" app:exitAnim="@anim/zoom_in_fade"
app:popEnterAnim="@anim/fade_in" /> app:popEnterAnim="@anim/zoom_out_fade" />
<action <action
android:id="@+id/action_homeFragment_to_libraryFragment" android:id="@+id/action_homeFragment_to_libraryFragment"
app:destination="@id/libraryFragment" /> app:destination="@id/libraryFragment" />