Added layout behavior to dismiss toolbars when scrolling
This commit is contained in:
parent
51247d36c5
commit
2daa131fb2
@ -3,8 +3,11 @@ package com.topjohnwu.magisk.redesign
|
|||||||
import android.graphics.Insets
|
import android.graphics.Insets
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.view.setPadding
|
import androidx.core.view.setPadding
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.ncapdevi.fragnav.FragNavController
|
import com.ncapdevi.fragnav.FragNavController
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.Const
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
@ -16,6 +19,7 @@ import com.topjohnwu.magisk.ui.log.LogFragment
|
|||||||
import com.topjohnwu.magisk.ui.module.ModulesFragment
|
import com.topjohnwu.magisk.ui.module.ModulesFragment
|
||||||
import com.topjohnwu.magisk.ui.settings.SettingsFragment
|
import com.topjohnwu.magisk.ui.settings.SettingsFragment
|
||||||
import com.topjohnwu.magisk.ui.superuser.SuperuserFragment
|
import com.topjohnwu.magisk.ui.superuser.SuperuserFragment
|
||||||
|
import com.topjohnwu.magisk.utils.HideTopViewOnScrollBehavior
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
@ -48,6 +52,9 @@ open class MainActivity : CompatActivity<MainViewModel, ActivityMainMd2Binding>(
|
|||||||
|
|
||||||
setSupportActionBar(binding.mainToolbar)
|
setSupportActionBar(binding.mainToolbar)
|
||||||
|
|
||||||
|
binding.mainToolbarWrapper.updateLayoutParams<CoordinatorLayout.LayoutParams> {
|
||||||
|
behavior = HideTopViewOnScrollBehavior<MaterialCardView>()
|
||||||
|
}
|
||||||
binding.mainNavigation.setOnNavigationItemSelectedListener {
|
binding.mainNavigation.setOnNavigationItemSelectedListener {
|
||||||
when (it.itemId) {
|
when (it.itemId) {
|
||||||
R.id.homeFragment -> Navigation.home()
|
R.id.homeFragment -> Navigation.home()
|
||||||
|
@ -0,0 +1,130 @@
|
|||||||
|
package com.topjohnwu.magisk.utils
|
||||||
|
|
||||||
|
import android.animation.TimeInterpolator
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.ViewPropertyAnimator
|
||||||
|
import androidx.annotation.Dimension
|
||||||
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
|
import com.google.android.material.animation.AnimationUtils
|
||||||
|
import com.google.android.material.behavior.HideBottomViewOnScrollBehavior
|
||||||
|
|
||||||
|
class HideTopViewOnScrollBehavior<V : View> : HideBottomViewOnScrollBehavior<V>() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val STATE_SCROLLED_DOWN = 1
|
||||||
|
private const val STATE_SCROLLED_UP = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
private var height = 0
|
||||||
|
private var currentState = STATE_SCROLLED_UP
|
||||||
|
private var additionalHiddenOffsetY = 0
|
||||||
|
private var currentAnimator: ViewPropertyAnimator? = null
|
||||||
|
|
||||||
|
override fun onLayoutChild(
|
||||||
|
parent: CoordinatorLayout,
|
||||||
|
child: V,
|
||||||
|
layoutDirection: Int
|
||||||
|
): Boolean {
|
||||||
|
val paramsCompat = child.layoutParams as ViewGroup.MarginLayoutParams
|
||||||
|
height = child.measuredHeight + paramsCompat.topMargin
|
||||||
|
return super.onLayoutChild(parent, child, layoutDirection)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an additional offset for the y position used to hide the view.
|
||||||
|
*
|
||||||
|
* @param child the child view that is hidden by this behavior
|
||||||
|
* @param offset the additional offset in pixels that should be added when the view slides away
|
||||||
|
*/
|
||||||
|
override fun setAdditionalHiddenOffsetY(child: V, @Dimension offset: Int) {
|
||||||
|
additionalHiddenOffsetY = offset
|
||||||
|
|
||||||
|
if (currentState == STATE_SCROLLED_DOWN) {
|
||||||
|
child.translationY = (height + additionalHiddenOffsetY).toFloat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartNestedScroll(
|
||||||
|
coordinatorLayout: CoordinatorLayout,
|
||||||
|
child: V,
|
||||||
|
directTargetChild: View,
|
||||||
|
target: View,
|
||||||
|
nestedScrollAxes: Int
|
||||||
|
) = nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
|
||||||
|
|
||||||
|
override fun onNestedScroll(
|
||||||
|
coordinatorLayout: CoordinatorLayout,
|
||||||
|
child: V,
|
||||||
|
target: View,
|
||||||
|
dxConsumed: Int,
|
||||||
|
dyConsumed: Int,
|
||||||
|
dxUnconsumed: Int,
|
||||||
|
dyUnconsumed: Int
|
||||||
|
) {
|
||||||
|
when {
|
||||||
|
dyConsumed > 0 -> slideUp(child)
|
||||||
|
dyConsumed < 0 -> slideDown(child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an animation that will slide the child from it's current position to be totally on the
|
||||||
|
* screen.
|
||||||
|
*/
|
||||||
|
override fun slideDown(child: V) {
|
||||||
|
if (currentState == STATE_SCROLLED_UP) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
currentAnimator?.let {
|
||||||
|
it.cancel()
|
||||||
|
child.clearAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
|
currentState = STATE_SCROLLED_UP
|
||||||
|
animateChildTo(
|
||||||
|
child,
|
||||||
|
0,
|
||||||
|
ENTER_ANIMATION_DURATION.toLong(),
|
||||||
|
AnimationUtils.LINEAR_OUT_SLOW_IN_INTERPOLATOR
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform an animation that will slide the child from it's current position to be totally off the
|
||||||
|
* screen.
|
||||||
|
*/
|
||||||
|
override fun slideUp(child: V) {
|
||||||
|
if (currentState == STATE_SCROLLED_DOWN) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
currentAnimator?.let {
|
||||||
|
it.cancel()
|
||||||
|
child.clearAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
|
currentState = STATE_SCROLLED_DOWN
|
||||||
|
animateChildTo(
|
||||||
|
child,
|
||||||
|
-(height + additionalHiddenOffsetY),
|
||||||
|
EXIT_ANIMATION_DURATION.toLong(),
|
||||||
|
AnimationUtils.FAST_OUT_LINEAR_IN_INTERPOLATOR
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun animateChildTo(
|
||||||
|
child: V,
|
||||||
|
targetY: Int,
|
||||||
|
duration: Long,
|
||||||
|
interpolator: TimeInterpolator
|
||||||
|
) = child
|
||||||
|
.animate()
|
||||||
|
.translationY(targetY.toFloat())
|
||||||
|
.setInterpolator(interpolator)
|
||||||
|
.setDuration(duration)
|
||||||
|
.withEndAction { currentAnimator = null }
|
||||||
|
.let { currentAnimator = it }
|
||||||
|
}
|
@ -28,6 +28,7 @@
|
|||||||
style="?styleCardElevated"
|
style="?styleCardElevated"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/main_toolbar_wrapper"
|
||||||
android:layout_marginStart="@dimen/l1"
|
android:layout_marginStart="@dimen/l1"
|
||||||
android:layout_marginTop="@{(int) @dimen/l1 + viewModel.insets.top}"
|
android:layout_marginTop="@{(int) @dimen/l1 + viewModel.insets.top}"
|
||||||
android:layout_marginEnd="@dimen/l1"
|
android:layout_marginEnd="@dimen/l1"
|
||||||
@ -55,6 +56,7 @@
|
|||||||
style="?styleCardElevated"
|
style="?styleCardElevated"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:layout_marginStart="@dimen/l1"
|
android:layout_marginStart="@dimen/l1"
|
||||||
android:layout_marginEnd="@dimen/l1"
|
android:layout_marginEnd="@dimen/l1"
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size + (int) @dimen/l2}"
|
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size + (int) @dimen/l2}"
|
||||||
android:paddingBottom="@{viewModel.insets.bottom + (int) @dimen/margin_fab + (int) @dimen/l1}"
|
android:paddingBottom="@{viewModel.insets.bottom + (int) @dimen/l1}"
|
||||||
tools:layout_marginTop="24dp">
|
tools:layout_marginTop="24dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
Loading…
Reference in New Issue
Block a user