Skip to content
This repository has been archived by the owner on Feb 20, 2023. It is now read-only.

For #4744 - Extract TransitionPreDrawListener #4812

Merged
merged 1 commit into from
Aug 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 12 additions & 27 deletions app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
Expand Down Expand Up @@ -113,21 +112,6 @@ class HomeFragment : Fragment(), AccountObserver {
}
}

private val preDrawListener = object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
if (view != null) {
viewLifecycleOwner.lifecycleScope.launch {
delay(ANIM_SCROLL_DELAY)
restoreLayoutState()
startPostponedEnterTransition()
}.invokeOnCompletion {
sessionControlComponent.view.viewTreeObserver.removeOnPreDrawListener(this)
}
}
return true
}
}

private var homeMenu: HomeMenu? = null

private val sessionManager: SessionManager
Expand Down Expand Up @@ -201,20 +185,22 @@ class HomeFragment : Fragment(), AccountObserver {
activity.themeManager.applyStatusBarTheme(activity)

postponeEnterTransition()
sessionControlComponent.view.viewTreeObserver.addOnPreDrawListener(preDrawListener)
TransitionPreDrawListener(
fragment = this,
viewTreeObserver = sessionControlComponent.view.viewTreeObserver,
restoreLayoutState = {
val homeViewModel: HomeScreenViewModel by activityViewModels()
homeViewModel.layoutManagerState?.also { parcelable ->
sessionControlComponent.view.layoutManager?.onRestoreInstanceState(parcelable)
}
homeLayout?.progress = homeViewModel.motionLayoutProgress
homeViewModel.layoutManagerState = null
}
)

return view
}

private fun restoreLayoutState() {
val homeViewModel: HomeScreenViewModel by activityViewModels()
homeViewModel.layoutManagerState?.also { parcelable ->
sessionControlComponent.view.layoutManager?.onRestoreInstanceState(parcelable)
}
homeLayout?.progress = homeViewModel.motionLayoutProgress
homeViewModel.layoutManagerState = null
}

@SuppressWarnings("LongMethod")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Expand Down Expand Up @@ -278,7 +264,6 @@ class HomeFragment : Fragment(), AccountObserver {

override fun onDestroyView() {
homeMenu = null
sessionControlComponent.view.viewTreeObserver.removeOnPreDrawListener(preDrawListener)
super.onDestroyView()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* 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/. */

package org.mozilla.fenix.home

import android.view.ViewTreeObserver
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class TransitionPreDrawListener(
private val fragment: Fragment,
private val viewTreeObserver: ViewTreeObserver,
private val restoreLayoutState: () -> Unit
) : ViewTreeObserver.OnPreDrawListener, LifecycleObserver {

init {
fragment.viewLifecycleOwner.lifecycle.addObserver(this)
}

@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreateView() {
viewTreeObserver.addOnPreDrawListener(this)
}

@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroyView() {
viewTreeObserver.removeOnPreDrawListener(this)
}

override fun onPreDraw(): Boolean {
if (fragment.view != null) {
fragment.viewLifecycleOwner.lifecycleScope.launch {
delay(ANIM_SCROLL_DELAY)
restoreLayoutState()
fragment.startPostponedEnterTransition()
}.invokeOnCompletion {
viewTreeObserver.removeOnPreDrawListener(this)
}
}
return true
}

companion object {
private const val ANIM_SCROLL_DELAY = 100L
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* 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/. */

package org.mozilla.fenix.home

import android.view.ViewTreeObserver
import androidx.fragment.app.Fragment
import io.mockk.mockk
import io.mockk.verify
import org.junit.Before
import org.junit.Test

class TransitionPreDrawListenerTest {

private lateinit var fragment: Fragment
private lateinit var viewTreeObserver: ViewTreeObserver

@Before
fun setup() {
fragment = mockk(relaxed = true)
viewTreeObserver = mockk(relaxed = true)
}

@Test
fun `adds observer when constructed`() {
val listener = TransitionPreDrawListener(fragment, viewTreeObserver) {}
verify { fragment.viewLifecycleOwner.lifecycle.addObserver(listener) }
}

@Test
fun `adds listener on create and removes on destroy`() {
val listener = TransitionPreDrawListener(fragment, viewTreeObserver) {}

listener.onCreateView()
verify { viewTreeObserver.addOnPreDrawListener(listener) }

listener.onDestroyView()
verify { viewTreeObserver.removeOnPreDrawListener(listener) }
}
}