具有固定/固定的工具栏和"enterAlways"功能的CollapsingToolbarLayout. [英] CollapsingToolbarLayout with fixed/pinned Toolbar and functionality of "enterAlways"
问题描述
我有一个基于材料设计指南的标准"CollapsingToolbarLayout"实现.
使用下面的设置,我可以实现图片上描绘的行为:
With the the settings below I was able to achieve behavior depicted on the picture:
<CoordinatorLayout ...>
<AppBarLayout ...>
<CollapsingToolbarLayout
app:layout_scrollFlags="scroll|enterAlways"
...>
<Toolbar
app:layout_collapseMode="pin">
</Toolbar>
<MyCustomContent01 ... />
</CollapsingToolbarLayout>
</AppBarLayout>
<MyCustomContent02 ... />
</CoordinatorLayout>
如何实现以下行为?
- 向上滚动:即使我们不在列表顶部,也始终完全展开工具栏.
- 向下滚动:只需折叠工具栏,但不要隐藏它.
- Scrolling up: always expand the Toolbar fully, even if we are not on the top of the list.
- Scrolling down: just collapse the Toolbar, but don't hide it.
换句话说:如何在保留步骤4的条件的同时摆脱步骤3?
In other words: How can I get rid of the step 3 while preserving the condition of step 4?
对我而言,关于该主题的最佳文章似乎就是这一篇,但是所提供的配置都不符合我的需求.
For me the best article on this topic seems to be this one, however none of the presented configurations match my needs.
尝试一个:
<CollapsingToolbarLayout
app:layout_scrollFlags="scroll|enterAlways"
...>
- 切勿完全隐藏工具栏(摆脱第3步):失败
- 即使我们不在顶部,也要展开工具栏:确定
- Never hide fully the Toolbar (getting rid of step 3): FAIL
- Expand the Toolbar even if we are not on the top: OK
尝试两个
<CollapsingToolbarLayout
app:layout_scrollFlags="scroll|exitUntilCollapsed"
...>
- 永远不要完全隐藏工具栏(摆脱第3步):确定
- 即使我们不在顶部,也可以展开工具栏:失败
- Never hide fully the Toolbar (getting rid of step 3): OK
- Expand the Toolbar even if we are not on the top: FAIL
推荐答案
Material库提供的默认CollapsingToolbarLayout仅限于一组预定义的动画.要创建我们自己的自定义效果,请说您要在RecyclerView/NestedScrollView上滚动时完全扩展标题布局,即使您不在滚动视图的顶部,也可以使用功能强大的
The default CollapsingToolbarLayout provided by the Material library is too limited to a set of predefined animations. To create our own custom effects, say you want to fully expand the header layout when scrolling up on the RecyclerView/ NestedScrollView even if you are not on top of the scroll view, you can use the powerful MotionLayout which is a subclass of ConstraintLayout for building animations. If you are happy to replace the existing view hierarchy with a flat Constraint-layout equivalent, read the detailed answer given below.
在这里,我将向您展示如何使用始终固定的页眉布局创建"enterAlways"效果,所有这些操作只需三个简单的步骤.
Here I am going to show you how to create the "enterAlways" effect with an always pinned header layout, all with in three simple steps.
在编写任何代码之前,请参阅下面给出的gif图片,以更好地了解我们正在尝试创建的内容.
Before writing any code, see the gif image given below to better understand what we are trying to create.
1.添加ConstraintLayout
依赖项:
1. Add the ConstraintLayout
dependency:
要在项目中使用MotionLayout,请将ConstraintLayout 2.0依赖项添加到应用程序的build.gradle文件中.如果您使用的是AndroidX,请添加以下依赖项:
To use MotionLayout in your project, add the ConstraintLayout 2.0 dependency to your app's build.gradle file. If you're using AndroidX, add the following dependency:
dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2'
}
如果您不使用AndroidX,请添加以下支持库依赖项:
dependencies {
implementation 'com.android.support.constraint:constraint-layout:2.0.0-beta2'
}
2.创建MotionLayout文件:
MotionLayout是ConstraintLayout的子类,因此您可以将任何现有的ConstraintLayout转换为MotionLayout.因此,如下所示创建一个布局文件.
MotionLayout is a subclass of ConstraintLayout, so you can transform any existing ConstraintLayout into a MotionLayout. So create one layout file as shown below.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
motion:layoutDescription="@xml/motionscene"
tools:showPaths="false">
<View
android:id="@+id/toolbar_image"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#345634"
android:fitsSystemWindows="true"
motion:layout_constraintBottom_toBottomOf="@id/toolbar"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:src="@drawable/abc_ic_ab_back_material"
android:tint="?android:attr/textColorPrimaryInverse"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/customHeader"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toEndOf="@id/home"
motion:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:id="@+id/row1"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="8dp">
<View
android:layout_width="20dp"
android:layout_height="20dp"
android:background="#345678" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="some text"
android:textColor="#ffffff" />
</LinearLayout>
<LinearLayout
android:id="@+id/row2"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:layout_marginRight="16dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="8dp">
<View
android:layout_width="20dp"
android:layout_height="20dp"
android:background="#345678" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="some text"
android:textColor="#ffffff" />
</LinearLayout>
<LinearLayout
android:id="@+id/row3"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:layout_marginRight="16dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="8dp">
<View
android:layout_width="20dp"
android:layout_height="20dp"
android:background="#345678" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="some text"
android:textColor="#ffffff" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/toolbar"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:background="#345634"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="8dp"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toEndOf="@id/home"
motion:layout_constraintTop_toBottomOf="@id/customHeader">
<View
android:layout_width="20dp"
android:layout_height="20dp"
android:background="#F44336" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:text="Toolbar Title"
android:textColor="#ffffff" />
<View
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginLeft="16dp"
android:background="#F44336" />
</LinearLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#ffffff"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toBottomOf="@+id/toolbar_image">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:text="@string/large_text" />
</androidx.core.widget.NestedScrollView>
</androidx.constraintlayout.motion.widget.MotionLayout>
3.创建MotionScene:
在上一步中,motion:layoutDescription属性引用了MotionScene. MotionScene是XML资源文件,其中包含对应布局的所有运动描述.为了使布局信息与运动描述分开,每个MotionLayout都引用一个单独的MotionScene.请注意,MotionScene中的定义优先于MotionLayout中的任何类似定义.
In the previous step, motion:layoutDescription attribute references a MotionScene. A MotionScene is an XML resource file that contains all of the motion descriptions for the corresponding layout. To keep layout information separate from motion descriptions, each MotionLayout references a separate MotionScene. Note that definitions in the MotionScene take precedence over any similar definitions in the MotionLayout.
以下是一个示例MotionScene文件,该文件创建具有'enterAlways'效果的所需固定/固定工具栏:
Following is a sample MotionScene file that creates the required fixed/pinned toolbar with 'enterAlways' effect:
将文件放在res目录下的xml文件夹中.
Put the file in the xml folder under the res directory.
motionscene.xml
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">
<Transition
motion:constraintSetEnd="@id/collapsed"
motion:constraintSetStart="@id/expanded">
<OnSwipe
motion:dragDirection="dragUp"
motion:moveWhenScrollAtTop="false"
motion:touchAnchorId="@id/scrollView"
motion:touchAnchorSide="top" />
</Transition>
<ConstraintSet android:id="@+id/expanded">
<Constraint android:id="@id/toolbar_image" />
<Constraint android:id="@id/toolbar" />
<Constraint android:id="@id/customHeader">
<PropertySet android:alpha="1" />
</Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/collapsed">
<Constraint
android:id="@id/toolbar_image"
android:layout_height="?attr/actionBarSize"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent">
</Constraint>
<Constraint
android:id="@id/customHeader"
android:layout_width="0dp"
android:layout_height="wrap_content"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toEndOf="@id/home"
motion:layout_constraintTop_toTopOf="parent">
<PropertySet android:alpha="0" />
</Constraint>
<Constraint
android:id="@id/toolbar"
android:layout_height="?attr/actionBarSize"
android:layout_marginStart="16dp"
android:layout_marginTop="0dp"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toEndOf="@id/home"
motion:layout_constraintTop_toTopOf="parent">
</Constraint>
</ConstraintSet>
</MotionScene>
仅此而已.您创建了一个惊人的自定义动画,而无需编写任何Java/kotlin代码. MotionLayout是完全声明性的,这意味着无论多么复杂,您都可以描述XML中的任何过渡.
That's all. You created an amazing custom animation with out writing any java/kotlin code. MotionLayout is fully declarative, meaning that you can describe any transitions in XML, no matter how complex.
Google的以下回购包含更多示例.
The following repo by Google includes more samples.
https://github.com/googlesamples/android-ConstraintLayoutExamples
这篇关于具有固定/固定的工具栏和"enterAlways"功能的CollapsingToolbarLayout.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!