MotionLayout 基礎教程 2

閱讀說明:php

  • 本文假設讀者已掌握如何使用 ConstraintLayout
  • 本文假設讀者已對 MotionLayout 有了基本瞭解,知道如何建立 MotionScene 文件,以及如何使用 MotionLayout 在兩個 layout 佈局文件間建立過渡動畫。如您徹底不瞭解這些,建議您閱讀 《MotionLayout 基礎教程》
  • 建議讀者在閱讀過程當中動手實踐,有助於更好的理解,如您如今不方便,建議稍後閱讀。
  • 因爲官方文檔不全,部份內容來自筆者的我的理解,若有錯誤,歡迎指正。

本文是 《MotionLayout 基礎教程》 的第 2 篇,主要向讀者介紹如何在 MotionScene 文件中定義場景約束以及如何使用自定義屬性。android

在 MotionScene 文件中定義約束

能夠在 <MotionScene> 元素中使用 <ConstraintSet> 子元素定義一個場景約束集,並在 <ConstraintSet> 元素中使用 <Constraint> 元素定義單個 View 的屬性約束。app

:在 MotionScene 文件中定義 End 場景的約束集框架

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- 定義 End 場景的約束集 -->
    <ConstraintSet android:id="@+id/activity_main_end">

        <!-- 定義佈局中 id 爲 image 的 View 的屬性約束 -->
        <Constraint android:id="@+id/button" android:layout_width="56dp" android:layout_height="56dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.0" />

    </ConstraintSet>

    <!-- Start 場景是佈局文件,End 場景是定義在 MotionScene 文件中的約束集 -->
    <Transition app:constraintSetStart="@layout/activity_main" app:constraintSetEnd="@id/activity_main_end" app:duration="1000">

        <OnClick app:clickAction="toggle" app:targetId="@id/button" />

    </Transition>

</MotionScene>
複製代碼

實際上,你便可以把 Start 場景的約束集定義在 MotionScene 文件中,也能夠把 End 場景的約束集定義在 MotionScene 文件中。或者僅在 MotionScene 文件中定義這二者之一,另外一個場景使用 layout 佈局文件定義。佈局

建議:建議把 Start 場景和 End 場景的約束集都定義在 MotionScene 文件中。由於 MotionLayout 框架某些特性(例如自定義屬性(下節會介紹))依賴於 MotionScene 文件中 Start 場景,若是 Start 場景沒有定義在 MotionScene 文件中,這些特性可能會沒法使用。post

:在 MotionScene 文件中定義 Start 場景約束與 End 場景約束(本示例分爲如下兩步)學習

1. 建立佈局文件:測試

文件名: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: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/activity_main_motion_scene">

    <Button android:id="@+id/button" android:layout_width="56dp" android:layout_height="56dp" android:background="@color/colorPrimary" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="1.0" />

</androidx.constraintlayout.motion.widget.MotionLayout>
複製代碼

提示:佈局文件仍是要有的,並非說將 Start 場景約束和 End 場景約束都定義在了 MotionScene 文件中就能夠不須要佈局文件了。spa

佈局文件預覽:

2. 建立 MotionScene 文件:

文件名:activity_main_motion_scene.xml

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- 定義 Start 場景的屬性約束集 -->
    <ConstraintSet android:id="@+id/activity_main_start">

        <!-- 定義佈局中 id 爲 button 的 View 的屬性約束 -->
        <Constraint android:id="@id/button" android:layout_width="56dp" android:layout_height="56dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="1.0" />

    </ConstraintSet>


    <!-- 定義 End 場景的屬性約束集 -->
    <ConstraintSet android:id="@+id/activity_main_end">

        <!-- 定義佈局中 id 爲 button 的 View 的屬性約束 -->
        <Constraint android:id="@+id/button" android:layout_width="56dp" android:layout_height="56dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.0" />

    </ConstraintSet>

    <!-- Start 場景與 End 場景都是定義在 MotionScene 文件中的約束集 -->
    <Transition app:constraintSetStart="@id/activity_main_start" app:constraintSetEnd="@id/activity_main_end" app:duration="1000">

        <OnClick app:clickAction="toggle" app:targetId="@id/button" />

    </Transition>

</MotionScene>
複製代碼

<ConstraintSet> 元素屬性說明:

  • android:id:設置當前約束集的 id。這個 id 值可被 <Transition> 元素的 app:constraintSetStart 或者 app:constraintSetEnd 引用。

<Constraint> 元素屬性說明:

  • android:id:當前約束關聯到的那個 Viewid
  • app:transitionEasing:定義動畫到此點時使用的緩動曲線,該值能夠是一個字符串(例如 "curve(1.0,0,0,1.0)")還能夠是如下幾個枚舉值之一:
    • standard:標準
    • accelerate:加速
    • decelerate:減速
    • linear:線性

提示 1<Constraint> 元素的 app:transitionEasing 屬性與 <Transition> 元素的 app:motionInterpolator 屬性相似,都是用來定義過渡動畫的插值器的。不一樣的是,<Constraint> 元素的 app:transitionEasing 屬性定義的是單獨某個 View 的過渡動畫的插值器,而 <Transition> 元素的 app:motionInterpolator 定義的是整個過渡動畫的插值器。

提示 2:若是爲 <Constraint> 元素指定了 app:transitionEasing 插值器,這個插值器將與 app:motionInterpolator 屬性指定的全局插值器同時做用於 View 的過渡動畫,而不是替換掉 app:motionInterpolator 屬性指定的全局插值器。

提示 3<Constraint> 元素的 app:transitionEasing 屬性值應該在 Start 場景中指定,(經測試)僅在 End 場景中指定 app:transitionEasing 沒法生效。

提示 4:(經測試,彷佛無效)可使用形如 "curve(1.0,0,0,1.0)" 的字符串來爲 <Constraint> 元素的 app:transitionEasing 屬性設置一個緩動曲線,MotionLayout 框架將根據這個緩動曲線來生成一個插值器。

  • app:transitionPathRotate:【浮點值】相對於所採用的路徑旋轉對象(弧形路徑/關鍵幀 相關)。
  • app:drawPath:繪製過渡動畫路徑(調試用,關鍵幀相關)。能夠是如下幾個枚舉值之一:
    • none
    • path
    • pathRelative
    • deltaRelative
    • asConfigured
    • rectangles
  • app:progress:【浮點值】在關聯的 View 上調用 setProgress(float) 方法(用於與嵌套的 ConstraintLayout 交互)

前面說過,<Constraint> 元素用來定義單個 View 的屬性約束,它支持對 View 的全部 ConstraintLayout 屬性定義約束,以及對 View 的下面這些標準屬性定義約束:

  • android:visibility
  • android:alpha
  • android:elevation
  • android:rotation
  • android:rotationX
  • android:rotationY
  • android:scaleX
  • android:scaleY
  • android:translationX
  • android:translationY
  • android:translationZ

View 的標準屬性或者 ConstraintLayout 屬性發生改變時,MotionLayout 會自動應用過渡動畫。

自定義屬性

MotionLayout 控件只會檢測標準屬性和 ConstraintLayout 屬性這類佈局相關的屬性變更,對於其餘的屬性變更,如 View 的背景顏色變更是沒法檢測出來的,所以就須要使用自定義屬性。

<Constraint> 元素中使用 <CustomAttribute> 子元素來指定自定義屬性。

例:

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- 定義 Start 場景的屬性約束集 -->
    <ConstraintSet android:id="@+id/activity_main_start">

        <!-- 定義佈局中 id 爲 image 的 View 的屬性約束 -->
        <Constraint android:id="@id/button" android:layout_width="56dp" android:layout_height="56dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="1.0">

            <!-- 使用自定義屬性 -->
            <CustomAttribute app:attributeName="backgroundColor" app:customColorValue="@color/colorPrimary" />

        </Constraint>

    </ConstraintSet>


    <!-- 定義 End 場景的屬性約束集 -->
    <ConstraintSet android:id="@+id/activity_main_end">

        <!-- 定義佈局中 id 爲 image 的 View 的屬性約束 -->
        <Constraint android:id="@+id/button" android:layout_width="56dp" android:layout_height="56dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.0">

            <!-- 使用自定義屬性 -->
            <CustomAttribute app:attributeName="backgroundColor" app:customColorValue="@color/colorAccent" />

        </Constraint>

    </ConstraintSet>

    <Transition app:constraintSetEnd="@id/activity_main_end" app:constraintSetStart="@id/activity_main_start" app:duration="1000">

        <OnClick app:clickAction="toggle" app:targetId="@id/button" />

    </Transition>

</MotionScene>
複製代碼

效果預覽:

<CustomAttribute> 元素屬性說明:

  • app:attributeName 屬性用來指定自定義屬性的名字(例如 "backgroundColor")。關聯的 View 必需要有一對與這個名字相關的 getter/setter 方法(例如 getBackgroundColor()/setBackgroundColor(int color))。
  • 剩下的其餘屬性都是用來設置自定義屬性的值的。須要根據自定義屬性的值類型使用如下 XML 屬性之一來設置自定義屬性的值:
    • app:customColorValue:設置屬性的值(顏色類型)。
    • app:customColorDrawableValue:設置屬性的值(顏色類型)。
    • app:customIntegerValue:設置屬性的值(整數類型)。
    • app:customFloatValue:設置屬性的值(浮點類型)。
    • app:customStringValue:設置屬性的值(字符串類型)。
    • app:customDimension:設置屬性的值(尺寸類型)。
    • app:customPixelDimension:設置屬性的值(尺寸類型)。
    • app:customBoolean:設置屬性的值(布爾類型)。

結語

本篇文章是 《MotionLayout 基礎教程》 的第 2 篇,閱讀完這兩篇文章後您基本就能掌握 MotionLayout 的基礎內容了。

寫這兩篇文章的主要目的是爲了向讀者介紹 MotionLayout 的基礎內容,讓讀者可以入門,並在此基礎上進一步學習。如您想要了解更多 MotionLayout 內容,推薦您閱讀如下 3 篇文章:

相關文章
相關標籤/搜索