即使嵌套滚动视图中没有滚动内容,折叠工具栏布局也会滚动
Collapsing Toolbar Layout Scroll even when there is no scrolling content in Nested Scroll View
我在我的项目中使用折叠工具栏布局,其中我使用一个 NestedScrollView
,其中我有多个卡片视图,其中内容不是静态的,而是在 onActivityResult
中变化。我已将 CollapsingToolbarLayout
的最小高度设置为 100dp。所以我观察到其中的几个问题:
- 在大手机上,内容会向上滚动到最小高度 100dp,在底部留下一个大空白 space,这不是我们想要的结果。它应该只在必要时向上滚动。必要条件是,当我在文本字段中获得大文本值时,它应该滚动,否则不会滚动。
- 我在其中使用了 Natario Solution,它可以动态计算
CollapsingToolbarLayout
的最小高度,但它会以某种方式工作,但它会消失 NestedScrollView
的滚动能力,如果我得到大的动态文本,这是不是想要的结果。
我的 layout.xml 文件是:-
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:clickable="true"
android:id="@+id/topBlock"
app:layout_constraintTop_toTopOf="parent"
android:focusable="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/navigation"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
app:elevation="0dp"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@null"
android:minHeight="100dp">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapse_bar"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@android:color/holo_blue_light"
android:minHeight="100dp"
app:layout_collapseMode="parallax"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:layout_scrollInterpolator="@android:anim/decelerate_interpolator">
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="8dp"
app:backgroundTint="@color/white"
app:fabSize="normal"
app:layout_anchor="@+id/nestedScrollView"
app:layout_anchorGravity="top|center_horizontal"
app:srcCompat="@drawable/ic_launcher_background" />
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:background="@color/white"
android:layout_height="wrap_content">
////My Scrolling Content(Contains many edit texts so its size may vary)
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
我没有在 MyActivity.kt 文件中做任何事情。请帮我解决这个问题。在过去的 15 天里,我已经尝试了这个社区中几乎所有的解决方案,但仍然没有成功。谢谢!!
编辑:按照建议,我已经将问题更新为 NestedScrollView
作为直接子项,并发布了 Android Studio 预览的屏幕截图,其中它正在获取正在穿越预览的高度。它应该根据 content.If 我制作 NestedScrollView
wrap_content 的高度然后它仍然在底部留空 space 。在后台我有相机 运行 所以我必须让它与父级匹配才能使封面全高。
首先,你有CoordinatorLayout
就不需要ConstraintLayout
了。另外正如用户在评论中提到的,NestedScrollView
应该是 CoordinatorLayout
的直接 child 而不是 ConstraintLayout
。按照您的这种方式设计,某些行为可能无法按预期工作,实际上是错误的设计。
我已经进行了更改,这是您在预览中看到的内容:
更新布局:
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/topBlock"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapse_bar"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@android:color/holo_blue_light"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:layout_scrollInterpolator="@android:anim/decelerate_interpolator">
<androidx.appcompat.widget.Toolbar
android:id="@+id/myToolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme"
app:title="Your title" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="40dp"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:text="MyRandomText"
android:textColor="@android:color/black"
android:textSize="42sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/view"
app:layout_constraintCircleRadius="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="20sp"
android:background="@android:color/holo_blue_light"
app:layout_constraintTop_toBottomOf="@id/title" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="8dp"
android:src="@mipmap/ic_launcher"
app:backgroundTint="@color/white"
app:fabSize="normal"
app:layout_anchor="@+id/nestedScrollView"
app:layout_anchorGravity="top|center_horizontal" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
P.S:还请记住NestedScrollView
应该只有一个child,因为它是第一个child。
这样才是正确的做法,您不必使用 kotlin-java 代码来实现滚动或其他行为,您将能够使用标志和属性来实现这些行为,例如layout_scrollFlags
和 exitUntilCollapsed
等。
对于您的问题我没有特别的解决方案,但我强烈建议您使用 Motion Layout。我也在开发一个带有 'collapsing toolbar' 的应用程序,我想做一个视差效果,就像在 Spotify 中一样。使用 Coordinator Layout 和 Collapsing Toolbar 真的很困难,而且关于它的文档不是很广泛所以老实说我不知道我在做什么。
我在网上研究了其他方法,最后我发现了这个。 Motion Layout 可让您 调整动画 细节。我知道考虑将整个布局从 CoordinatorLayout 更改为 MotionLayout 似乎需要大量工作,但事实并非如此。如果有的话,它是有益的,因为 MotionLayout 从 ConstraintLayout 扩展而来,并且您可以为布局的每个视图设置动画(如果您的父级是 MotionLayout)。另一个支持 ML 的论点是你有动画监听器:例如,当一个转换完成时,一个方法被自动调用,这样你就可以在需要时链接动画,这真的很有趣。
查看可以使用 Motion Layout 构建的一些可能的动画。它们带有布局 xml 和动画 xml,因此您可以从中学习(很棒的官方文档 btw):
https://developer.android.com/training/constraint-layout/motionlayout/examples
这是我用来模仿协调器布局中折叠工具栏行为的教程:
https://blog.stylingandroid.com/motionlayout-collapsing-toolbar-part-1/
https://blog.stylingandroid.com/motionlayout-collapsing-toolbar-part-2/
(我个人刚刚完成了第 1 部分,然后自己继续)
我在我的项目中使用折叠工具栏布局,其中我使用一个 NestedScrollView
,其中我有多个卡片视图,其中内容不是静态的,而是在 onActivityResult
中变化。我已将 CollapsingToolbarLayout
的最小高度设置为 100dp。所以我观察到其中的几个问题:
- 在大手机上,内容会向上滚动到最小高度 100dp,在底部留下一个大空白 space,这不是我们想要的结果。它应该只在必要时向上滚动。必要条件是,当我在文本字段中获得大文本值时,它应该滚动,否则不会滚动。
- 我在其中使用了 Natario Solution,它可以动态计算
CollapsingToolbarLayout
的最小高度,但它会以某种方式工作,但它会消失NestedScrollView
的滚动能力,如果我得到大的动态文本,这是不是想要的结果。
我的 layout.xml 文件是:-
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:clickable="true"
android:id="@+id/topBlock"
app:layout_constraintTop_toTopOf="parent"
android:focusable="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/navigation"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
app:elevation="0dp"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@null"
android:minHeight="100dp">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapse_bar"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@android:color/holo_blue_light"
android:minHeight="100dp"
app:layout_collapseMode="parallax"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:layout_scrollInterpolator="@android:anim/decelerate_interpolator">
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="8dp"
app:backgroundTint="@color/white"
app:fabSize="normal"
app:layout_anchor="@+id/nestedScrollView"
app:layout_anchorGravity="top|center_horizontal"
app:srcCompat="@drawable/ic_launcher_background" />
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:background="@color/white"
android:layout_height="wrap_content">
////My Scrolling Content(Contains many edit texts so its size may vary)
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
我没有在 MyActivity.kt 文件中做任何事情。请帮我解决这个问题。在过去的 15 天里,我已经尝试了这个社区中几乎所有的解决方案,但仍然没有成功。谢谢!!
编辑:按照建议,我已经将问题更新为 NestedScrollView
作为直接子项,并发布了 Android Studio 预览的屏幕截图,其中它正在获取正在穿越预览的高度。它应该根据 content.If 我制作 NestedScrollView
wrap_content 的高度然后它仍然在底部留空 space 。在后台我有相机 运行 所以我必须让它与父级匹配才能使封面全高。
首先,你有CoordinatorLayout
就不需要ConstraintLayout
了。另外正如用户在评论中提到的,NestedScrollView
应该是 CoordinatorLayout
的直接 child 而不是 ConstraintLayout
。按照您的这种方式设计,某些行为可能无法按预期工作,实际上是错误的设计。
我已经进行了更改,这是您在预览中看到的内容:
更新布局:
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/topBlock"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapse_bar"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@android:color/holo_blue_light"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:layout_scrollInterpolator="@android:anim/decelerate_interpolator">
<androidx.appcompat.widget.Toolbar
android:id="@+id/myToolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme"
app:title="Your title" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="40dp"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:text="MyRandomText"
android:textColor="@android:color/black"
android:textSize="42sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/view"
app:layout_constraintCircleRadius="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="20sp"
android:background="@android:color/holo_blue_light"
app:layout_constraintTop_toBottomOf="@id/title" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="8dp"
android:src="@mipmap/ic_launcher"
app:backgroundTint="@color/white"
app:fabSize="normal"
app:layout_anchor="@+id/nestedScrollView"
app:layout_anchorGravity="top|center_horizontal" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
P.S:还请记住NestedScrollView
应该只有一个child,因为它是第一个child。
这样才是正确的做法,您不必使用 kotlin-java 代码来实现滚动或其他行为,您将能够使用标志和属性来实现这些行为,例如layout_scrollFlags
和 exitUntilCollapsed
等。
对于您的问题我没有特别的解决方案,但我强烈建议您使用 Motion Layout。我也在开发一个带有 'collapsing toolbar' 的应用程序,我想做一个视差效果,就像在 Spotify 中一样。使用 Coordinator Layout 和 Collapsing Toolbar 真的很困难,而且关于它的文档不是很广泛所以老实说我不知道我在做什么。
我在网上研究了其他方法,最后我发现了这个。 Motion Layout 可让您 调整动画 细节。我知道考虑将整个布局从 CoordinatorLayout 更改为 MotionLayout 似乎需要大量工作,但事实并非如此。如果有的话,它是有益的,因为 MotionLayout 从 ConstraintLayout 扩展而来,并且您可以为布局的每个视图设置动画(如果您的父级是 MotionLayout)。另一个支持 ML 的论点是你有动画监听器:例如,当一个转换完成时,一个方法被自动调用,这样你就可以在需要时链接动画,这真的很有趣。
查看可以使用 Motion Layout 构建的一些可能的动画。它们带有布局 xml 和动画 xml,因此您可以从中学习(很棒的官方文档 btw): https://developer.android.com/training/constraint-layout/motionlayout/examples
这是我用来模仿协调器布局中折叠工具栏行为的教程: https://blog.stylingandroid.com/motionlayout-collapsing-toolbar-part-1/ https://blog.stylingandroid.com/motionlayout-collapsing-toolbar-part-2/ (我个人刚刚完成了第 1 部分,然后自己继续)