如何实现滚动行为,其中工具栏和底部导航都应该隐藏?只有其中一个在工作
How do I achieve on scroll behavior where both the toolbar and bottom navigation should hide?Only one of them is working
我正在尝试实现协调器布局行为,在滚动回收器视图时可以隐藏工具栏和底部导航视图。到目前为止,我已经取得了一项成功,即底部导航底部栏确实隐藏了,但有一个警告,即使键盘打开它也保持活动状态(我该如何解决这个问题?)
我主要关心的是如何实现隐藏到工具栏中的底部导航视图的相同功能?
我已经在 Appbar 布局中包含了自定义工具栏,但我也尝试在 AppBar 中添加工具栏布局标签没有任何效果,它只是保持不变。
对于跳到顶部的底部导航,我不知道该怎么办?到目前为止,我已经在底部导航视图上添加了 snap
滚动标志以停止此行为,并且快照标志也不起作用,我认为是这样,因为它在搜索点击时保持在中间位置。
从精彩的文章中获得了这个 BottomNavigationBehavior。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:elevation="0dp"
android:background="@android:color/transparent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
<include
app:layout_scrollFlags="scroll|enterAlways|snap"
layout="@layout/browser_search_tap_tb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/browser_tb"
/>
</com.google.android.material.appbar.AppBarLayout>
<!--Scrolling effect for the bottom nav menu-->
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/rv_test_items"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/rv_test"
/>
<!--Bottom navigation view for the Selection of the Tabs and Items in Menu-->
<com.google.android.material.bottomnavigation.BottomNavigationView
app:layout_scrollFlags="scroll|enterAlways|snap"
android:id="@+id/browser_bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#ffff"
app:layout_behavior="com.example.android.browserui.BottomNavigationBehavior"
app:labelVisibilityMode="unlabeled"
app:menu="@menu/bottom_nav_menu"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
browser_search_tap_tb.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="@android:color/transparent"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat"
app:contentInsetStart="8dp"
app:contentInsetEnd="8dp"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="0dp"
android:layout_height="match_parent"
android:hint="Search or type new address"
android:padding="8dp"
android:paddingEnd="12dp"
android:paddingStart="12dp"
android:drawableEnd="@drawable/ic_mic"
android:inputType="textWebEditText"
android:background="@drawable/rounded_et_search"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" android:id="@+id/et_search_bar_tap"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.Toolbar>
BottomNavigationBehavior.kt
class BottomNavigationBehavior<V : View>(context: Context, attrs: AttributeSet) :
CoordinatorLayout.Behavior<V>(context, attrs) {
private var lastStartedType: Int = 0
private var offsetAnimator: ValueAnimator? = null
var isSnappingEnabled = false
override fun layoutDependsOn(parent: CoordinatorLayout, child: V, dependency: View): Boolean {
if (dependency is Snackbar.SnackbarLayout) {
updateSnackbar(child, dependency)
}
return super.layoutDependsOn(parent, child, dependency)
}
override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout, child: V, directTargetChild: View, target: View, axes: Int, type: Int
): Boolean {
if (axes != ViewCompat.SCROLL_AXIS_VERTICAL)
return false
lastStartedType = type
offsetAnimator?.cancel()
return true
}
override fun onNestedPreScroll(
coordinatorLayout: CoordinatorLayout, child: V, target: View, dx: Int, dy: Int, consumed: IntArray, type: Int
) {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
child.translationY = max(0f, min(child.height.toFloat(), child.translationY + dy))
}
override fun onStopNestedScroll(coordinatorLayout: CoordinatorLayout, child: V, target: View, type: Int) {
if (!isSnappingEnabled)
return
// add snap behaviour
// Logic here borrowed from AppBarLayout onStopNestedScroll code
if (lastStartedType == ViewCompat.TYPE_TOUCH || type == ViewCompat.TYPE_NON_TOUCH) {
// find nearest seam
val currTranslation = child.translationY
val childHalfHeight = child.height * 0.5f
// translate down
if (currTranslation >= childHalfHeight) {
animateBarVisibility(child, isVisible = false)
}
// translate up
else {
animateBarVisibility(child, isVisible = true)
}
}
}
private fun animateBarVisibility(child: View, isVisible: Boolean) {
if (offsetAnimator == null) {
offsetAnimator = ValueAnimator().apply {
interpolator = DecelerateInterpolator()
duration = 150L
}
offsetAnimator?.addUpdateListener {
child.translationY = it.animatedValue as Float
}
} else {
offsetAnimator?.cancel()
}
val targetTranslation = if (isVisible) 0f else child.height.toFloat()
offsetAnimator?.setFloatValues(child.translationY, targetTranslation)
offsetAnimator?.start()
}
private fun updateSnackbar(child: View, snackbarLayout: Snackbar.SnackbarLayout) {
if (snackbarLayout.layoutParams is CoordinatorLayout.LayoutParams) {
val params = snackbarLayout.layoutParams as CoordinatorLayout.LayoutParams
params.anchorId = child.id
params.anchorGravity = Gravity.TOP
params.gravity = Gravity.TOP
snackbarLayout.layoutParams = params
}
}
}
所以终于解决了我的问题,经过 4 天的思考,这里是我所做的一些更改并解决了问题:
activity_main.xml
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:elevation="0dp"
android:background="@android:color/transparent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"<!--Removed this line-->
>
<!--Bottom navigation view for the Selection of the Tabs and Items in Menu-->
<com.google.android.material.bottomnavigation.BottomNavigationView
app:layout_scrollFlags="scroll|enterAlways|snap"<!--Removed this line-->
android:id="@+id/browser_bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#ffff"
app:layout_behavior="com.example.android.browserui.BottomNavigationBehavior"
app:labelVisibilityMode="unlabeled"
app:menu="@menu/bottom_nav_menu"
/>
在 activity_main.xml 中,我删除了 layout_behavior 因为 appbar 本身正在调用其他布局项的滚动行为,它充当父项。
app:layout_behavior="@string/appbar_scrolling_view_behavior"
还从底部导航视图中删除了 scrollflags,因为我从 Class BottomNavigationBehavior.kt 实现了此行为,您可以在下面找到实现
app:layout_scrollFlags="scroll|enterAlways|snap"
browser_search_tap_tb.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="@android:color/transparent"
app:layout_scrollFlags="scroll|enterAlways" <!--Removed this line-->
app:popupTheme="@style/ThemeOverlay.AppCompat"
app:contentInsetStart="8dp"
app:contentInsetEnd="8dp"
>
在 browser_search_tb 中,我删除了以下行,因为它覆盖了协调器布局中的 Scrollflags,因此将其删除并且它完美地工作
app:layout_scrollFlags="scroll|enterAlways"
BottomNavigationBehavior.kt
override fun onStopNestedScroll(coordinatorLayout: CoordinatorLayout, child: V, target: View, type: Int) {
if (!isSnappingEnabled)
return // removed this line
{
// add snap behaviour
// Logic here borrowed from AppBarLayout onStopNestedScroll code
if (lastStartedType == ViewCompat.TYPE_TOUCH || type == ViewCompat.TYPE_NON_TOUCH) {
// find nearest seam
val currTranslation = child.translationY
val childHalfHeight = child.height * 0.5f
// translate down
if (currTranslation >= childHalfHeight) {
animateBarVisibility(child, isVisible = false)
}
// translate up
else {
animateBarVisibility(child, isVisible = true)
}
}
}
}
这里我去掉了
return
并在 if 语句中添加了大括号{},并且 snap 功能正常工作
希望这个回答能对您有所帮助,并减少您的调试时间。
上面的参考资料是您可以在互联网上找到的关于滚动行为的最好的文章之一,它简单易懂
我正在尝试实现协调器布局行为,在滚动回收器视图时可以隐藏工具栏和底部导航视图。到目前为止,我已经取得了一项成功,即底部导航底部栏确实隐藏了,但有一个警告,即使键盘打开它也保持活动状态(我该如何解决这个问题?) 我主要关心的是如何实现隐藏到工具栏中的底部导航视图的相同功能?
我已经在 Appbar 布局中包含了自定义工具栏,但我也尝试在 AppBar 中添加工具栏布局标签没有任何效果,它只是保持不变。
对于跳到顶部的底部导航,我不知道该怎么办?到目前为止,我已经在底部导航视图上添加了 snap
滚动标志以停止此行为,并且快照标志也不起作用,我认为是这样,因为它在搜索点击时保持在中间位置。
从精彩的文章中获得了这个 BottomNavigationBehavior。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:elevation="0dp"
android:background="@android:color/transparent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
<include
app:layout_scrollFlags="scroll|enterAlways|snap"
layout="@layout/browser_search_tap_tb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/browser_tb"
/>
</com.google.android.material.appbar.AppBarLayout>
<!--Scrolling effect for the bottom nav menu-->
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:listitem="@layout/rv_test_items"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/rv_test"
/>
<!--Bottom navigation view for the Selection of the Tabs and Items in Menu-->
<com.google.android.material.bottomnavigation.BottomNavigationView
app:layout_scrollFlags="scroll|enterAlways|snap"
android:id="@+id/browser_bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#ffff"
app:layout_behavior="com.example.android.browserui.BottomNavigationBehavior"
app:labelVisibilityMode="unlabeled"
app:menu="@menu/bottom_nav_menu"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
browser_search_tap_tb.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="@android:color/transparent"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat"
app:contentInsetStart="8dp"
app:contentInsetEnd="8dp"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="0dp"
android:layout_height="match_parent"
android:hint="Search or type new address"
android:padding="8dp"
android:paddingEnd="12dp"
android:paddingStart="12dp"
android:drawableEnd="@drawable/ic_mic"
android:inputType="textWebEditText"
android:background="@drawable/rounded_et_search"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" android:id="@+id/et_search_bar_tap"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.appcompat.widget.Toolbar>
BottomNavigationBehavior.kt
class BottomNavigationBehavior<V : View>(context: Context, attrs: AttributeSet) :
CoordinatorLayout.Behavior<V>(context, attrs) {
private var lastStartedType: Int = 0
private var offsetAnimator: ValueAnimator? = null
var isSnappingEnabled = false
override fun layoutDependsOn(parent: CoordinatorLayout, child: V, dependency: View): Boolean {
if (dependency is Snackbar.SnackbarLayout) {
updateSnackbar(child, dependency)
}
return super.layoutDependsOn(parent, child, dependency)
}
override fun onStartNestedScroll(
coordinatorLayout: CoordinatorLayout, child: V, directTargetChild: View, target: View, axes: Int, type: Int
): Boolean {
if (axes != ViewCompat.SCROLL_AXIS_VERTICAL)
return false
lastStartedType = type
offsetAnimator?.cancel()
return true
}
override fun onNestedPreScroll(
coordinatorLayout: CoordinatorLayout, child: V, target: View, dx: Int, dy: Int, consumed: IntArray, type: Int
) {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type)
child.translationY = max(0f, min(child.height.toFloat(), child.translationY + dy))
}
override fun onStopNestedScroll(coordinatorLayout: CoordinatorLayout, child: V, target: View, type: Int) {
if (!isSnappingEnabled)
return
// add snap behaviour
// Logic here borrowed from AppBarLayout onStopNestedScroll code
if (lastStartedType == ViewCompat.TYPE_TOUCH || type == ViewCompat.TYPE_NON_TOUCH) {
// find nearest seam
val currTranslation = child.translationY
val childHalfHeight = child.height * 0.5f
// translate down
if (currTranslation >= childHalfHeight) {
animateBarVisibility(child, isVisible = false)
}
// translate up
else {
animateBarVisibility(child, isVisible = true)
}
}
}
private fun animateBarVisibility(child: View, isVisible: Boolean) {
if (offsetAnimator == null) {
offsetAnimator = ValueAnimator().apply {
interpolator = DecelerateInterpolator()
duration = 150L
}
offsetAnimator?.addUpdateListener {
child.translationY = it.animatedValue as Float
}
} else {
offsetAnimator?.cancel()
}
val targetTranslation = if (isVisible) 0f else child.height.toFloat()
offsetAnimator?.setFloatValues(child.translationY, targetTranslation)
offsetAnimator?.start()
}
private fun updateSnackbar(child: View, snackbarLayout: Snackbar.SnackbarLayout) {
if (snackbarLayout.layoutParams is CoordinatorLayout.LayoutParams) {
val params = snackbarLayout.layoutParams as CoordinatorLayout.LayoutParams
params.anchorId = child.id
params.anchorGravity = Gravity.TOP
params.gravity = Gravity.TOP
snackbarLayout.layoutParams = params
}
}
}
所以终于解决了我的问题,经过 4 天的思考,这里是我所做的一些更改并解决了问题: activity_main.xml
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:elevation="0dp"
android:background="@android:color/transparent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"<!--Removed this line-->
>
<!--Bottom navigation view for the Selection of the Tabs and Items in Menu-->
<com.google.android.material.bottomnavigation.BottomNavigationView
app:layout_scrollFlags="scroll|enterAlways|snap"<!--Removed this line-->
android:id="@+id/browser_bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#ffff"
app:layout_behavior="com.example.android.browserui.BottomNavigationBehavior"
app:labelVisibilityMode="unlabeled"
app:menu="@menu/bottom_nav_menu"
/>
在 activity_main.xml 中,我删除了 layout_behavior 因为 appbar 本身正在调用其他布局项的滚动行为,它充当父项。
app:layout_behavior="@string/appbar_scrolling_view_behavior"
还从底部导航视图中删除了 scrollflags,因为我从 Class BottomNavigationBehavior.kt 实现了此行为,您可以在下面找到实现
app:layout_scrollFlags="scroll|enterAlways|snap"
browser_search_tap_tb.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="@android:color/transparent"
app:layout_scrollFlags="scroll|enterAlways" <!--Removed this line-->
app:popupTheme="@style/ThemeOverlay.AppCompat"
app:contentInsetStart="8dp"
app:contentInsetEnd="8dp"
>
在 browser_search_tb 中,我删除了以下行,因为它覆盖了协调器布局中的 Scrollflags,因此将其删除并且它完美地工作
app:layout_scrollFlags="scroll|enterAlways"
BottomNavigationBehavior.kt
override fun onStopNestedScroll(coordinatorLayout: CoordinatorLayout, child: V, target: View, type: Int) {
if (!isSnappingEnabled)
return // removed this line
{
// add snap behaviour
// Logic here borrowed from AppBarLayout onStopNestedScroll code
if (lastStartedType == ViewCompat.TYPE_TOUCH || type == ViewCompat.TYPE_NON_TOUCH) {
// find nearest seam
val currTranslation = child.translationY
val childHalfHeight = child.height * 0.5f
// translate down
if (currTranslation >= childHalfHeight) {
animateBarVisibility(child, isVisible = false)
}
// translate up
else {
animateBarVisibility(child, isVisible = true)
}
}
}
}
这里我去掉了
return
并在 if 语句中添加了大括号{},并且 snap 功能正常工作
希望这个回答能对您有所帮助,并减少您的调试时间。 上面的参考资料是您可以在互联网上找到的关于滚动行为的最好的文章之一,它简单易懂