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),
arguments = arguments!!
).apply {
beginAnimationIfNecessary()
beginAnimateInIfNecessary()
}
return getSessionById()?.also { session ->

View File

@ -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()
}
/**

View File

@ -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"
}
}

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