MotionLayout
là một loại bố cục giúp bạn quản lý chuyển động và ảnh động tiện ích trong ứng dụng. MotionLayout
là một lớp con của ConstraintLayout
và dựa trên các chức năng bố cục phong phú của lớp này. Là một phần của thư viện ConstraintLayout
, MotionLayout
có sẵn dưới dạng thư viện hỗ trợ.
MotionLayout
giúp kết nối khoảng cách giữa các hiệu ứng chuyển đổi bố cục và tính năng xử lý chuyển động phức tạp, cung cấp một tổ hợp các tính năng giữa khung ảnh động thuộc tính, TransitionManager
và CoordinatorLayout
.
Ngoài việc mô tả các hiệu ứng chuyển đổi giữa các bố cục, MotionLayout
còn cho phép bạn tạo ảnh động cho bất kỳ thuộc tính bố cục nào. Hơn nữa, tính năng này vốn hỗ trợ các hiệu ứng chuyển đổi có thể tua lại. Điều này có nghĩa là bạn có thể hiển thị tức thì bất kỳ điểm nào trong quá trình chuyển đổi dựa trên một số điều kiện, chẳng hạn như đầu vào cảm ứng. MotionLayout
cũng hỗ trợ các khung hình chính, cho phép chuyển đổi tuỳ chỉnh hoàn toàn cho phù hợp với nhu cầu của bạn.
MotionLayout
mang tính khai báo đầy đủ, nghĩa là bạn có thể mô tả mọi hiệu ứng chuyển đổi trong XML, bất kể phức tạp đến mức nào.
Cân nhắc về thiết kế
MotionLayout
dùng để di chuyển, đổi kích thước và tạo ảnh động cho các phần tử trên giao diện người dùng mà người dùng tương tác, chẳng hạn như nút và thanh tiêu đề. Đừng sử dụng chuyển động trong ứng dụng của bạn làm hiệu ứng đặc biệt vô bổ. Sử dụng thông báo này để giúp người dùng hiểu được ứng dụng của bạn đang làm gì. Để biết thêm thông tin về cách thiết kế ứng dụng có chuyển động, hãy xem phần Tìm hiểu về chuyển động trong Material Design.
Bắt đầu
Hãy làm theo các bước sau để bắt đầu sử dụng MotionLayout
trong dự án của bạn.
-
Thêm phần phụ thuộc
ConstraintLayout
: để sử dụngMotionLayout
trong dự án, hãy thêm phần phụ thuộcConstraintLayout
2.0 vào tệpbuild.gradle
của ứng dụng. Nếu bạn đang sử dụng AndroidX, hãy thêm phần phụ thuộc sau:Groovy
dependencies { implementation "androidx.constraintlayout:constraintlayout:2.2.0-beta01" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-beta01" }
Kotlin
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.0-beta01") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-beta01") }
-
Tạo tệp
MotionLayout
:MotionLayout
là một lớp con củaConstraintLayout
, vì vậy, bạn có thể chuyển đổi mọiConstraintLayout
hiện có thànhMotionLayout
bằng cách thay thế tên lớp trong tệp tài nguyên bố cục, như trong các ví dụ sau:AndroidX
<!-- before: ConstraintLayout --> <androidx.constraintlayout.widget.ConstraintLayout .../> <!-- after: MotionLayout --> <androidx.constraintlayout.motion.widget.MotionLayout .../>
Thư viện hỗ trợ
<!-- before: ConstraintLayout --> <android.support.constraint.ConstraintLayout .../> <!-- after: MotionLayout --> <android.support.constraint.motion.MotionLayout .../>
Dưới đây là ví dụ đầy đủ về tệp
MotionLayout
, xác định bố cục hiển thị trong hình 1:AndroidX
<?xml version="1.0" encoding="utf-8"?> <!-- activity_main.xml --> <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:id="@+id/motionLayout" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutDescription="@xml/scene_01" tools:showPaths="true"> <View android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:background="@color/colorAccent" android:text="Button" /> </androidx.constraintlayout.motion.widget.MotionLayout>
Thư viện hỗ trợ
<?xml version="1.0" encoding="utf-8"?> <!-- activity_main.xml --> <android.support.constraint.motion.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:id="@+id/motionLayout" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutDescription="@xml/scene_01" tools:showPaths="true"> <View android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:background="@color/colorAccent" android:text="Button" /> </android.support.constraint.motion.MotionLayout>
-
Tạo MotionScene: trong ví dụ
MotionLayout
trước, thuộc tínhapp:layoutDescription
tham chiếu đến một cảnh chuyển động. Cảnh chuyển động là một tệp tài nguyên XML. Trong phần tử gốc<MotionScene>
, cảnh chuyển động chứa tất cả nội dung mô tả chuyển động cho bố cục tương ứng. Để tách riêng thông tin bố cục với nội dung mô tả chuyển động, mỗiMotionLayout
sẽ tham chiếu đến một cảnh chuyển động riêng biệt. Các định nghĩa trong cảnh chuyển động được ưu tiên hơn mọi định nghĩa tương tự trongMotionLayout
.Dưới đây là tệp cảnh chuyển động mẫu mô tả chuyển động ngang cơ bản trong hình 1:
<?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:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000"> <OnSwipe motion:touchAnchorId="@+id/button" motion:touchAnchorSide="right" motion:dragDirection="dragRight" /> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" 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="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
Xin lưu ý những điều sau:
-
<Transition>
chứa định nghĩa cơ sở của chuyển động.-
motion:constraintSetStart
vàmotion:constraintSetEnd
là các tệp tham chiếu đến các điểm cuối của chuyển động. Các điểm cuối này được xác định trong các phần tử<ConstraintSet>
sau trong cảnh chuyển động. -
motion:duration
chỉ định số mili giây cần thiết để hoàn tất chuyển động.
-
-
<OnSwipe>
cho phép bạn tạo tính năng điều khiển cảm ứng cho chuyển động.-
motion:touchAnchorId
đề cập đến thành phần hiển thị mà người dùng có thể vuốt và kéo. -
motion:touchAnchorSide
có nghĩa là thành phần hiển thị đang được kéo từ phía bên phải. -
motion:dragDirection
cho biết hướng tiến trình của thao tác kéo. Ví dụ:motion:dragDirection="dragRight"
có nghĩa là tiến trình sẽ tăng khi khung hiển thị được kéo sang phải.
-
-
<ConstraintSet>
là nơi bạn xác định các điều kiện ràng buộc mô tả chuyển động của mình. Trong ví dụ này, một<ConstraintSet>
được xác định cho mỗi điểm cuối của chuyển động. Các điểm cuối này được căn giữa theo chiều dọc bằng cách sử dụngapp:layout_constraintTop_toTopOf="parent"
vàapp:layout_constraintBottom_toBottomOf="parent"
. Theo chiều ngang, các điểm cuối nằm ở phía bên trái và bên phải của màn hình.
Để xem chi tiết hơn về các phần tử mà cảnh chuyển động hỗ trợ, hãy xem ví dụ về MotionLayout.
-
Thuộc tính nội suy
Trong tệp cảnh chuyển động, các phần tử ConstraintSet
có thể chứa các thuộc tính bổ sung được nội suy trong quá trình chuyển đổi. Ngoài vị trí và giới hạn, MotionLayout
còn nội suy các thuộc tính sau:
alpha
visibility
elevation
rotation
,rotationX
,rotationY
translationX
,translationY
,translationZ
scaleX
,scaleY
Thuộc tính tùy chỉnh
Trong <Constraint>
, bạn có thể sử dụng phần tử <CustomAttribute>
để chỉ định chuyển đổi cho các thuộc tính không chỉ liên quan đến vị trí hoặc thuộc tính View
.
<Constraint android:id="@+id/button" ...> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60"/> </Constraint>
<CustomAttribute>
chứa hai thuộc tính riêng:
motion:attributeName
là bắt buộc và phải so khớp một đối tượng với các phương thức getter và setter. Phương thức getter và setter phải khớp với một mẫu cụ thể. Ví dụ:backgroundColor
được hỗ trợ vì khung hiển thị có các phương thứcgetBackgroundColor()
vàsetBackgroundColor()
cơ bản.- Thuộc tính khác mà bạn phải cung cấp dựa trên loại giá trị. Chọn trong số các loại được hỗ trợ sau:
motion:customColorValue
cho màumotion:customIntegerValue
cho số nguyênmotion:customFloatValue
cho số thựcmotion:customStringValue
cho chuỗimotion:customDimension
cho phương diệnmotion:customBoolean
cho boolean
Khi chỉ định một thuộc tính tuỳ chỉnh, hãy xác định các giá trị điểm cuối trong cả phần tử <ConstraintSet>
đầu và cuối.
Thay đổi màu nền
Dựa trên ví dụ trước, giả sử bạn muốn màu sắc của thành phần hiển thị thay đổi trong quá trình chuyển động của thành phần hiển thị đó, như minh hoạ trong hình 2.
Thêm một phần tử <CustomAttribute>
vào mỗi phần tử ConstraintSet
, như minh hoạ trong đoạn mã sau đây:
<ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#9999FF" /> </Constraint> </ConstraintSet>
Các thuộc tính MotionLayout bổ sung
Ngoài các thuộc tính trong ví dụ trước, MotionLayout
có các thuộc tính khác mà bạn có thể muốn chỉ định:
app:applyMotionScene="boolean"
cho biết liệu có áp dụng cảnh chuyển động hay không. Giá trị mặc định của thuộc tính này làtrue
.app:showPaths="boolean"
cho biết liệu có hiển thị các đường dẫn chuyển động khi chuyển động đang chạy hay không. Giá trị mặc định của thuộc tính này làfalse
.app:progress="float"
cho phép bạn chỉ định rõ tiến trình chuyển đổi. Bạn có thể sử dụng bất kỳ giá trị dấu phẩy động nào từ0
(bắt đầu chuyển đổi) đến1
(kết thúc chuyển đổi).app:currentState="reference"
cho phép bạn chỉ định mộtConstraintSet
cụ thể.app:motionDebug
cho phép bạn hiển thị thêm thông tin gỡ lỗi về chuyển động. Các giá trị có thể là"SHOW_PROGRESS"
,"SHOW_PATH"
hoặc"SHOW_ALL"
.
Tài nguyên khác
Để biết thêm thông tin về MotionLayout
, hãy xem các tài nguyên sau:
- Android nâng cao trong Kotlin 03.2: Ảnh động với MotionLayout
- Ví dụ về MotionLayout
- Mẫu MotionLayout/ConstraintLayout trên GitHub
- Giới thiệu về MotionLayout (phần I)
- Giới thiệu về MotionLayout (phần II)
- Giới thiệu về MotionLayout (phần III)
- Giới thiệu về MotionLayout (phần IV)