Explain 1. X, which provides static layout support, has expanded MotionLayout to optimize dynamic layout support, making nested scrolling layout, which was not possible in Interpret 1. X, very simple.

When there is no ConstraintLayout, nesting scroll layout is usually realized by using CoordinatorLayout. However, it has great limitations. There are only a few kinds of nesting layout that can be realized very easily. In this way, nested rolling layout has become a more complex layout, and the emergence of MotionLayout can perfectly solve such a layout problem.

In constraintLayout2.x, there are two ways to implement nested scroll layouts.

CoordinatorLayout cooperate MotionLayout

In fact, CoordinatorLayout is an early implementation, and if you are familiar with CoordinatorLayout, you can quickly adapt the existing code to accommodate the nested scrolling of MotionLayout.

The layout structure of this scheme is as follows:

CoordinatorLayout

——–AppBarLayout

—————-MotionLayout

——–NestedScrollView

CollapsingToolbarLayout in AppBarLayout CollapsingToolbarLayout CollapsingToolbarLayout uses MotionLayout to CollapsingToolbarLayout.

The general structure of this approach is as follows.

In AppBarLayout, we control the animation with MotionLayout.

So here, general and two routines, one is the direct use of MotionLayout, and inside the code through AppBarLayout OnOffsetChangedListener callback, set MotionLayout progress, The other is a custom MotionLayout directly, realize AppBarLayout. OnOffsetChangedListener, such versatility is strong, the sample is as follows.

class CollapsibleToolbar @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : MotionLayout(context, attrs, defStyleAttr), AppBarLayout.OnOffsetChangedListener { override fun onOffsetChanged(appBarLayout: AppBarLayout? , verticalOffset: Int) { progress = -verticalOffset / appBarLayout? .totalScrollRange? .toFloat()!! } override fun onAttachedToWindow() { super.onAttachedToWindow() (parent as? AppBarLayout)? .addOnOffsetChangedListener(this) } }Copy the code

The two methods are not fundamentally different, but the MotionEditor has some problems creating constraints on non-root layouts (as well as modifying properties) with custom motionLayouts, so if you use custom MotionLayouts, It is recommended to use the new root layout as a custom MotionLayout through include, while using the MotionLayout directly does not have this limitation. We hope that the MotionEditor can improve this problem as soon as possible. PS: Good news, Android Studio Arctic Fox has fixed this issue.

Simple MotionLayout implementation

MotionLayout is designed to replace the dynamic model of the layout, so if you use CoordinatorLayout, it’s not working for you, so what we do is we get rid of it, And only use MotionLayout to achieve nested scrolling effect, to achieve a unified scrolling layout.

The general structure of this routine is shown below.

MotionLayout

——–MotionLayout

——–NestedScrollView

We can see that there are two motionLayouts. The outer MotionLayout controls the layout of the head, and the inner MotionLayout controls the scrolling of the head.

In this way, the whole nesting scrolling pattern is suddenly open, no longer the previous use of CoordinatorLayout height restrictions, effect restrictions, all the content can be set through constraints, and then through MotionLayout dynamic constraints, so as to achieve nesting scrolling layout.

For the outer MotionLayout, its Scene provides two functions. One is to control the header from 200DP to 56DP, which provides a scaling function. Another important and easily overlooked function is to provide progress data to the inner MotionLayout. With this progress, you can coordinate the internal MotionLayout, which is the same way that you set the progress when you use CoordinatorLayout with the MotionLayout.

Let’s take a look at the outermost Scene. The code is shown below.

<? The 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/end" motion:constraintSetStart="@+id/start"> <OnSwipe motion:dragDirection="dragUp" motion:touchAnchorId="@+id/motionLayout" motion:touchAnchorSide="bottom" /> </Transition> <ConstraintSet android:id="@+id/start"> <ConstraintOverride android:id="@id/motionLayout" android:layout_height="200dp" motion:motionProgress="0" /> </ConstraintSet> <ConstraintSet  android:id="@+id/end"> <ConstraintOverride android:id="@id/motionLayout" android:layout_height="56dp" motion:motionProgress="1" /> </ConstraintSet> </MotionScene>Copy the code

ConstraintOverride For non-layout_constraintxxx_toxxXof constraints, ConstraintOverride can be used to override ConstraintOverride. The constraint changes from layout_height from 200 to 56. Another important point is to specify the motionProgress. The function of motionProgress is to set the motionProgress. If this is not set, the progress data cannot be passed to the internal MotionLayout, which will cause the internal linkage failure.

Once you’ve solved the external MotionLayout, the internal MotionLayout is a normal MotionLayout, and any changes you want to make to the internal elements are no different from the ones you used before.

Let’s take a look at this simple example, as shown.

Head stretching and text movement, a simple type of CoordinatorLayout layout, we have solved the external Scene, then look at the internal Scene, forget it, there is no need, it is simple physical labor.

The layout structure of the whole routine is shown below.

In general, MotionLayout is not to achieve a unified, it will scroll layout effect, into a multi-layer MotionLayout Scene decomposition, using progress in series, the design idea is not not fine, once you master the various basic layout of MotionLayout, So even if the layout is complicated, it can be divided and ruled.

I would like to recommend my website xuyisheng. Top/focusing on Android-Kotlin-flutter welcome you to visit