motionlayout_MotionLayout入门指南

motionlayout

什么是MotionLayout? (What Is MotionLayout?)

MotionLayout is a subclass of ConstraintLayout that includes all of its outstanding features, and it’s fully declarative with the capability to implement complicated transitions in the XML. It is backward-compatible with API level 14, which means it covers 99% of use cases.

MotionLayoutConstraintLayout的子类,它包含所有出色的功能,并且完全声明了XML的功能。 它与API级别14向后兼容,这意味着它涵盖了99%的用例。

The new MotionLayout editor in Android Studio 4.0 makes it easy to work with MotionLayout. It provides a fancy environment to implement transitions, MotionScenes, and more.

Android Studio 4.0中新的MotionLayout编辑器使使用MotionLayout变得容易。 它提供了一个精美的环境来实现转场, MotionScenes等。

为什么我们需要MotionLayout? (Why Do We Need MotionLayout?)

Implementing animations in Android is a complicated thing. We have various APIs, such as View Animations, Object Animator, Animated Vector Drawables, Transitions, and more. Sometimes, developers get confused about where to use which API. This is where MotionLayout comes handy.

在Android中实现动画是一件复杂的事情。 我们有各种API,例如“查看动画”,“对象动画师”,“可绘制矢量动画”,“过渡”等。 有时,开发人员会对在哪里使用哪个API感到困惑。 这是MotionLayout派上用场的地方。

MotionLayout is a new and effective way to implement transitions in Android. It acts as a bridge between the layout transitions and complex motion handling, providing a mix of features among the property animation framework, TransitionManager, and CoordinatorLayout.

MotionLayout是在Android中实现过渡的一种新的有效方法。 它充当布局过渡和复杂运动处理之间的桥梁,在属性动画框架TransitionManagerCoordinatorLayout之间提供了多种功能。

MotionLayout is intended to resize, move, and animate UI elements. However, it has a few limitations:

MotionLayout旨在调整UI元素的大小,移动和设置动画。 但是,它有一些限制:

  • It only supports animating MotionLayout's direct children.

    它仅支持对MotionLayout的直接子项进行动画MotionLayout

  • We can’t implement activity transitions.

    我们无法实现活动转换。

术语 (Terminology)

There are a few terms we need to learn before using MotionLayout.

在使用MotionLayout之前,我们需要学习一些术语。

运动场景 (MotionScene)

A MotionScene is an XML resource in the project that is used to write motion descriptions for each MotionLayout. This XML file starts with a MotionScene tag and contains all the necessary information related to the motions in that layout.

MotionScene是项目中的XML资源,用于为每个MotionLayout编写运动描述。 该XML文件以MotionScene标记开头,并包含与该布局中的动作有关的所有必要信息。

约束集 (ConstraintSet)

ConstraintSet is an XML tag that we use inside MotionScene to describe each endpoint of our motion. We can create as many ConstraintSets as we want based on the requirement.

ConstraintSet是一个XML标签,我们在MotionScene内部使用它来描述运动的每个端点。 我们可以根据需求创建任意数量的ConstraintSets

约束 (Constraint)

Constraint is another XML tag that we use inside ConstraintSet. This is where we can use all the features of ConstraintLayout. On each endpoint of the motion, we can use this tag to set the view based on transition.

Constraint是我们在ConstraintSet内部使用的另一个XML标记。 在这里我们可以使用ConstraintLayout所有功能。 在运动的每个端点上,我们都可以使用此标记基于过渡设置视图。

过渡 (Transition)

Transition is an XML tag that defines the motion between two ConstraintSets using the constraintSetStart and constraintSetEnd attributes. We can also mention the duration of the transition using this attribute. Along with these basic things, we can do the actual transition-related code here.

Transition是一个XML标记,它使用constraintSetStartconstraintSetEnd属性定义了两个ConstraintSets之间的运动。 我们也可以使用此属性提及过渡的持续时间。 除了这些基本内容,我们还可以在此处执行与转换相关的实际代码。

You will learn more about this tag in the later sections of this article.

您将在本文的后续部分中了解有关此标记的更多信息。

关键帧集 (KeyFrameSet)

It is used to specify the location and attributes of the views throughout the motion. With this sturdy XML tag, we can implement complex transitions. The attributes like KeyPosition and KeyAttribute are used to enforce transitions on the views at a particular moment.

它用于指定整个运动中视图的位置和属性。 有了这个坚固的XML标签,我们可以实现复杂的转换。 诸如KeyPositionKeyAttribute类的属性用于在特定时刻对视图强制执行过渡。

To better understand how all these tags and attributes connect, let’s create a simple MotionScene. Have a look:

为了更好地理解所有这些标签和属性如何连接,让我们创建一个简单的MotionScene 。 看一看:

<?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">


    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/button"
            android:layout_width="60dp"
            android:layout_height="60dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>


    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/button"
            android:layout_width="60dp"
            android:layout_height="60dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>
  
  <Transition
        motion:constraintSetStart="@+id/start"
        motion:constraintSetEnd="@+id/end"
        motion:duration="1000">
        
    // This is where all the keyframe and other things were implemented.
    
    </Transition>


</MotionScene>

layoutDescription (layoutDescription)

This is an attribute that we use in Motionlayout to link the MotionScene XML resource file.

这是我们在Motionlayout使用的属性,用于链接MotionScene XML资源文件。

显示路径 (showpaths)

This attribute is used to enable debug mode during transitions. It comes in handy once you get familiar with MotionLayout.

此属性用于在过渡期间启用调试模式。 一旦熟悉MotionLayout它就会派上用场。

Let’s create a simple piece of code showing how to use these attributes:

让我们创建一个简单的代码片段,展示如何使用这些属性:

<androidx.constraintlayout.motion.widget.MotionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/motionLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/scene_01"
    tools:showPaths="true"
    >
    ...
</androidx.constraintlayout.motion.widget.MotionLayout>

这个怎么运作 (How It Works)

Before diving into the implementation, it’s essential to learn how it works while doing the transitions as a beginner.

在深入研究实现之前,必须以入门者的身份学习它的工作原理。

First, we need to create a layout file with MotionLayout as the root tag. Always remember that Motionlayout can only animate its direct children. Nested hierarchy transitions won’t work with MotionLayout.

首先,我们需要创建一个以MotionLayout为根标签的布局文件。 永远记住, Motionlayout只能为其直接子对象设置动画。 嵌套的层次结构过渡不适用于MotionLayout

Then we need to implement the actual layout with all the views. Once it is finished, we need to create a MotionScene resource file under the res/xml folder to define the necessary motions.

然后,我们需要使用所有视图来实现实际的布局。 完成后,我们需要在res/xml文件夹下创建一个MotionScene资源文件,以定义必要的动作。

The MotionScene XML file is the core part of implementing the transitions. We can create as many endpoints as we like using the ConstraintSet tag and apply transitions between them using the Transition tag.

MotionScene XML文件是实现过渡的核心部分。 我们可以使用ConstraintSet标签创建任意数量的端点,并使用Transition标签在端点之间应用过渡。

Once you’re done with the MotionScene file, link it with the actual layout using the layoutDescription attribute. That’s all we need to do. To better understand it, let’s implement a Twitter splash screen animation with MotionLayout.

一旦完成了MotionScene文件,就可以使用layoutDescription属性将其与实际布局链接。 这就是我们要做的。 为了更好地理解它,让我们使用MotionLayout实现Twitter初始屏幕动画。

积分 (Integration)

As I said, MotionLayout is a subclass of ConstraintLayout, so we don’t need to integrate a new library. We need to update the version of ConstraintLayout. At the time of writing, the latest release is 2.0.0-beta6, but always make sure that you’re using the latest version.

如我所说, MotionLayoutConstraintLayout的子类,因此我们不需要集成新的库。 我们需要更新ConstraintLayout的版本。 在撰写本文时,最新版本是2.0.0-beta6 ,但是请始终确保您使用的是最新版本。

dependencies {
    implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta6'
}

Twitter用MotionLayout飞溅动画 (Twitter Splash Animation With MotionLayout)

创建一个简单的Twitter初始布局 (Creating a simple Twitter splash layout)

As the first step, we need to create a layout file with the MotionLayout root tag. Have a look at the layout file:

第一步,我们需要使用MotionLayout根标记创建一个布局文件。 看一下布局文件:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >


</androidx.constraintlayout.motion.widget.MotionLayout>

The next step is to create the views. Here, it is a simple ImageView with a Twitter icon aligned at the center of the screen. We need to apply the Twitter theme color as the background to the root tag. Have a look:

下一步是创建视图。 在这里,它是一个简单的ImageView ,其Twitter图标对准屏幕中心。 我们需要将Twitter主题颜色作为背景应用于根标签。 看一看:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#2f95fe"
    >


    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/ic_twitter_icon"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
  
</androidx.constraintlayout.motion.widget.MotionLayout>

实施MotionScene (Implementing MotionScene)

Now that we’re done with the layout implementation, it’s time to create a MotionScene. Before we start implementing, let’s be clear about what we’re trying to achieve. Have a look:

现在我们已经完成了布局实现,是时候创建一个MotionScene 。 在开始实施之前,让我们先弄清楚我们要实现的目标。 看一看:

Image for post

If we look at the transition carefully, we can see there are two animations:

如果我们仔细看一下过渡,我们可以看到有两个动画:

  • First, the Twitter icon scales down a bit.

    首先,Twitter图标会缩小一点。
  • After a moment, it scales to full screen.

    片刻之后,它将缩放到全屏。

We now need to create a MotionScene XML file under res/xml with the name twitter_motion_scene. Have a look:

现在,我们需要在res/xml下创建一个名称为twitter_motion_sceneMotionScene 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">


    
</MotionScene>

Now, we need endpoints to create a transition. We can create the endpoints of the motion using the ConstrainSet tag. In the first set, we need to mention the placement of the Twitter icon, as we want it at the center. In the second set, we don’t need to do anything. Have a look:

现在,我们需要端点来创建过渡。 我们可以使用ConstrainSet标记创建运动的端点。 在第一组中,我们需要提及Twitter图标的位置,因为我们希望它位于中心位置。 在第二组中,我们不需要执行任何操作。 看一看:

<ConstraintSet
    android:id="@+id/start">
    <Constraint
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:id="@+id/imageView"
        motion:layout_constraintTop_toTopOf="parent"
        motion:layout_constraintStart_toStartOf="parent"
        motion:layout_constraintEnd_toEndOf="parent"
        motion:layout_constraintBottom_toBottomOf="parent"
        />
</ConstraintSet>
<ConstraintSet android:id="@+id/end"
    >

The id attribute in the MotionScene indicates the view in the layout.

MotionSceneid属性指示布局中的视图。

Now, we have two endpoints in which we can animate the views. It’s time to create a transition between the ConstraintSets. First, we need to mention start and endpoints using the constraintSetStart and constraintSetEnd attributes, respectively.

现在,我们有两个端点可以在其中创建视图动画。 现在该在ConstraintSets之间创建过渡了。 首先,我们需要分别使用constraintSetStartconstraintSetEnd属性提及起点和终点。

Then we need to scale the Twitter icon a bit smaller than the original size. After a moment, we need to scale it back to standard size. Finally, it should scale to full screen. To implement this, we used KeyFrameSet and KeyAttribute. Have a look:

然后,我们需要缩放Twitter图标,使其比原始大小小一点。 片刻之后,我们需要将其缩放回标准大小。 最后,它应该缩放到全屏。 为了实现这一点,我们使用了KeyFrameSetKeyAttribute 。 看一看:

<Transition
    android:id="@+id/transition"
    motion:constraintSetStart="@+id/start"
    motion:constraintSetEnd="@+id/end"
    motion:autoTransition="animateToEnd">
    <KeyFrameSet >
        <KeyAttribute
            motion:motionTarget="@+id/imageView"
            motion:framePosition="20"
            android:scaleX="0.7"
            android:scaleY="0.7" />
        <KeyAttribute
            motion:motionTarget="@+id/imageView"
            motion:framePosition="50"
            android:scaleX="1.0"
            android:scaleY="1.0" />
        <KeyAttribute
            motion:motionTarget="@+id/imageView"
            motion:framePosition="100"
            android:scaleX="15.0"
            android:scaleY="15.0"
            android:alpha="0.1"/>
    </KeyFrameSet>
</Transition>

Here, we have three KeyAttributes to scale the icon down, bring it back to standard size, and finally scale it to full screen. framePosition is the key attribute and that is when the appropriate scaling should happen.

在这里,我们有三个KeyAttributes来缩小图标,将其恢复为标准大小,最后将其缩放为全屏。 framePosition是关键属性,也就是应该进行适当缩放的时间。

When we put everything together, it looks like this:

当我们将所有内容放在一起时,它看起来像这样:

<?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">


    <ConstraintSet
        android:id="@+id/start">
        <Constraint
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:id="@+id/imageView"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintBottom_toBottomOf="parent"
            />
    </ConstraintSet>


    <ConstraintSet android:id="@+id/end"
        >


    </ConstraintSet>
    <Transition
        android:id="@+id/transition"
        motion:constraintSetStart="@+id/start"
        motion:constraintSetEnd="@+id/end"
        motion:autoTransition="animateToEnd">
        <KeyFrameSet >
            <KeyAttribute
                motion:motionTarget="@+id/imageView"
                motion:framePosition="20"
                android:scaleX="0.7"
                android:scaleY="0.7" />
            <KeyAttribute
                motion:motionTarget="@+id/imageView"
                motion:framePosition="50"
                android:scaleX="1.0"
                android:scaleY="1.0" />


            <KeyAttribute
                motion:motionTarget="@+id/imageView"
                motion:framePosition="100"
                android:scaleX="15.0"
                android:scaleY="15.0"
                android:alpha="0.1"/>
        </KeyFrameSet>
    </Transition>
</MotionScene>

将MotionScene与布局文件链接 (Linking MotionScene with the layout file)

To wrap up, we need to link the MotionScene with the layout file. We can do this by using the layoutDescription attribute in the MotionLayout node. Have a look:

最后,我们需要将MotionScene与布局文件链接。 我们可以通过使用MotionLayout节点中的layoutDescription属性来执行此操作。 看一看:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#2f95fe"
    app:layoutDescription="@xml/twitter_animation_layout_scene">


    <ImageView
        android:id="@+id/imageView"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@drawable/ic_twitter_icon"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.motion.widget.MotionLayout>

观察过渡状态 (Observe transition status)

It’s almost done, but there’s one thing left: After the completion of the transition, we have to navigate to another activity. To implement this, we need to add a listener to observe MotionLayout’s transition status.

差不多完成了,但是还有一件事:过渡完成后,我们必须导航到另一个活动。 为了实现这一点,我们需要添加一个侦听器以观察MotionLayout'的过渡状态。

MotionLayout supports this out of the box. We need to use setTransitionListener on the MotionLayout. In the onTransitionCompleted callback, we need to invoke the code to navigate. Have a look:

MotionLayout支持此功能。 我们需要在MotionLayout上使用setTransitionListener 。 在onTransitionCompleted回调中,我们需要调用代码进行导航。 看一看:

motionlayout?.setTransitionListener(object : MotionLayout.TransitionListener {
    override fun onTransitionCompleted(p0: MotionLayout?, p1: Int) {
        startActivity(Intent(this@MainActivity, SecondActivity::class.java))
        finish()
    }
    override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) { }
    override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) { }
    override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) { }
})

结论 (Conclusion)

Feel free to play around with this on GitHub.

可以在GitHub上随意使用它。

To learn more about advanced Android development, read the following articles:

要了解有关高级Android开发的更多信息,请阅读以下文章:

That is all for now. I hope you learned something useful. Thanks for reading.

到此为止。 我希望你学到了一些有用的东西。 谢谢阅读。

翻译自: https://medium.com/better-programming/beginners-guide-to-motion-layout-732395a7de7e

motionlayout

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值