For #2899 - Improve collections scroll and highlight animations

nightly-build-test
Emily Kager 5 years ago committed by Emily Kager
parent e458d8b6a1
commit 510b6f7373

@ -22,6 +22,9 @@ import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders import androidx.lifecycle.ViewModelProviders
import androidx.navigation.fragment.FragmentNavigator import androidx.navigation.fragment.FragmentNavigator
import androidx.navigation.fragment.NavHostFragment.findNavController import androidx.navigation.fragment.NavHostFragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE
import androidx.transition.TransitionInflater import androidx.transition.TransitionInflater
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.fragment_home.* import kotlinx.android.synthetic.main.fragment_home.*
@ -692,48 +695,71 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
emitAccountChanges() emitAccountChanges()
} }
private fun scrollToCollections(addedTabsSize: Int) { private fun scrollAndAnimateCollection(addedTabsSize: Int, changedCollection: TabCollection? = null) {
launch { launch {
val recyclerView = sessionControlComponent.view
delay(ANIM_SCROLL_DELAY) delay(ANIM_SCROLL_DELAY)
val tabsSize = requireComponents.core.sessionManager.sessions.filter { val tabsSize = requireComponents.core.sessionManager.sessions.filter {
(activity as HomeActivity).browsingModeManager.isPrivate == it.private (activity as HomeActivity).browsingModeManager.isPrivate == it.private
}.size }.size
sessionControlComponent.view.smoothScrollToPosition(tabsSize + NON_TAB_ITEM_NUM) var indexOfCollection = tabsSize + NON_TAB_ITEM_NUM
delay(ANIM_SNACKBAR_DELAY) changedCollection?.let { changedCollection ->
showSavedSnackbar(addedTabsSize) requireComponents.core.tabCollectionStorage.cachedTabCollections.filterIndexed { index, tabCollection ->
if (tabCollection.id == changedCollection.id) {
indexOfCollection = tabsSize + NON_TAB_ITEM_NUM + index
return@filterIndexed true
}
false
}
}
val lastVisiblePosition =
(recyclerView.layoutManager as? LinearLayoutManager)?.findLastCompletelyVisibleItemPosition() ?: 0
if (lastVisiblePosition < indexOfCollection) {
val onScrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (newState == SCROLL_STATE_IDLE) {
animateCollection(addedTabsSize = addedTabsSize, indexOfCollection = indexOfCollection)
recyclerView.removeOnScrollListener(this)
}
}
}
recyclerView.addOnScrollListener(onScrollListener)
recyclerView.smoothScrollToPosition(indexOfCollection)
} else {
animateCollection(addedTabsSize = addedTabsSize, indexOfCollection = indexOfCollection)
}
} }
} }
private fun animateTopCollection() { private fun animateCollection(addedTabsSize: Int, indexOfCollection: Int) {
launch { launch {
delay(ANIM_SCROLL_DELAY) val viewHolder = sessionControlComponent.view.findViewHolderForAdapterPosition(indexOfCollection)
val tabsSize = requireComponents.core.sessionManager.sessions.filter {
(activity as HomeActivity).browsingModeManager.isPrivate == it.private
}.size
val topCollectionPosition = tabsSize + NON_TAB_ITEM_NUM
sessionControlComponent.view.smoothScrollToPosition(topCollectionPosition)
val viewHolder = sessionControlComponent.view.findViewHolderForAdapterPosition(topCollectionPosition)
val border = (viewHolder as? CollectionViewHolder)?.view?.findViewById<View>(R.id.selected_border) val border = (viewHolder as? CollectionViewHolder)?.view?.findViewById<View>(R.id.selected_border)
val listener = object : Animator.AnimatorListener { val listener = object : Animator.AnimatorListener {
override fun onAnimationCancel(animation: Animator?) {} override fun onAnimationCancel(animation: Animator?) {
border?.visibility = View.GONE
}
override fun onAnimationStart(animation: Animator?) {} override fun onAnimationStart(animation: Animator?) {}
override fun onAnimationRepeat(animation: Animator?) {} override fun onAnimationRepeat(animation: Animator?) {}
override fun onAnimationEnd(animation: Animator?) { override fun onAnimationEnd(animation: Animator?) {
border?.animate()?.alpha(0.0F)?.setDuration(FADE_ANIM_DURATION) border?.animate()?.alpha(0.0F)?.setStartDelay(ANIM_ON_SCREEN_DELAY)
?.setStartDelay(ANIM_ON_SCREEN_DELAY) ?.setDuration(FADE_ANIM_DURATION)
?.start() ?.start()
} }
} }
delay(ANIM_ON_SCREEN_DELAY) border?.animate()?.alpha(1.0F)?.setStartDelay(ANIM_ON_SCREEN_DELAY)?.setDuration(FADE_ANIM_DURATION)
border?.animate()?.alpha(1.0F)?.setDuration(FADE_ANIM_DURATION)?.setListener(listener)?.start() ?.setListener(listener)?.start()
}.invokeOnCompletion {
showSavedSnackbar(addedTabsSize)
} }
} }
private val collectionStorageObserver = object : TabCollectionStorage.Observer { private val collectionStorageObserver = object : TabCollectionStorage.Observer {
override fun onCollectionCreated(title: String, sessions: List<Session>) { override fun onCollectionCreated(title: String, sessions: List<Session>) {
super.onCollectionCreated(title, sessions) super.onCollectionCreated(title, sessions)
scrollToCollections(sessions.size) scrollAndAnimateCollection(sessions.size)
animateTopCollection()
} }
override fun onTabsAdded( override fun onTabsAdded(
@ -741,7 +767,7 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
sessions: List<Session> sessions: List<Session>
) { ) {
super.onTabsAdded(tabCollection, sessions) super.onTabsAdded(tabCollection, sessions)
scrollToCollections(sessions.size) scrollAndAnimateCollection(sessions.size, tabCollection)
} }
override fun onCollectionRenamed( override fun onCollectionRenamed(
@ -754,13 +780,16 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
} }
private fun showSavedSnackbar(tabSize: Int) { private fun showSavedSnackbar(tabSize: Int) {
context?.let { context: Context -> launch {
view?.let { view: View -> delay(ANIM_SNACKBAR_DELAY)
val string = context?.let { context: Context ->
if (tabSize > 1) context.getString(R.string.create_collection_tabs_saved) else view?.let { view: View ->
context.getString(R.string.create_collection_tab_saved) val string =
val snackbar = FenixSnackbar.make(view, Snackbar.LENGTH_LONG).setText(string) if (tabSize > 1) context.getString(R.string.create_collection_tabs_saved) else
snackbar.show() context.getString(R.string.create_collection_tab_saved)
val snackbar = FenixSnackbar.make(view, Snackbar.LENGTH_LONG).setText(string)
snackbar.show()
}
} }
} }
} }
@ -780,7 +809,7 @@ class HomeFragment : Fragment(), CoroutineScope, AccountObserver {
private const val ANIM_SCROLL_DELAY = 100L private const val ANIM_SCROLL_DELAY = 100L
private const val ANIM_ON_SCREEN_DELAY = 200L private const val ANIM_ON_SCREEN_DELAY = 200L
private const val FADE_ANIM_DURATION = 150L private const val FADE_ANIM_DURATION = 150L
private const val ANIM_SNACKBAR_DELAY = 500L private const val ANIM_SNACKBAR_DELAY = 100L
private const val SHARED_TRANSITION_MS = 200L private const val SHARED_TRANSITION_MS = 200L
private const val TAB_ITEM_TRANSITION_NAME = "tab_item" private const val TAB_ITEM_TRANSITION_NAME = "tab_item"
private const val toolbarPaddingDp = 12f private const val toolbarPaddingDp = 12f

Loading…
Cancel
Save