MotionLayout
là một loại bố cục giúp bạn quản lý chuyển động và hoạt ảnh của 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. Trong thư viện ConstraintLayout, MotionLayout có sẵn dưới dạng thư viện hỗ trợ.
MotionLayout thu hẹp khoảng cách giữa các hiệu ứng chuyển đổi bố cục và việc xử lý chuyển động phức tạp, cung cấp nhiều 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 hiệu ứng động cho mọi thuộc tính bố cục. Ngoài ra, nó vốn hỗ trợ các hiệu ứng chuyển đổi có thể tìm kiếm. Điều này có nghĩa là bạn có thể ngay lập tức hiện 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ư thao tác chạm. MotionLayout cũng hỗ trợ các khung hình chính, cho phép bạn tuỳ chỉnh hoàn toàn các hiệu ứng chuyển đổi cho phù hợp với nhu cầu của mình.
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.
Cân nhắc về thiết kế
MotionLayout được dùng để di chuyển, thay đổ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 dùng chuyển động trong ứng dụng của bạn như một hiệu ứng đặc biệt không cần thiết. Hãy dùng thông báo này để giúp người dùng hiểu được những việc mà ứng dụng của bạn đang làm. Để biết thêm thông tin về cách thiết kế ứng dụng bằng 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ụngMotionLayouttrong dự án, hãy thêm phần phụ thuộcConstraintLayout2.0 vào tệpbuild.gradlecủ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.1" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.1" }
Kotlin
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.1") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.1") }
-
Tạo tệp
MotionLayout:MotionLayoutlà một lớp con củaConstraintLayout, vì vậy, bạn có thể chuyển đổi mọiConstraintLayouthiện có thànhMotionLayoutbằng cách thay thế tên lớp trong tệp tài nguyên bố cục, như minh hoạ 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 xuất hiện 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ụ
MotionLayouttrước, thuộc tínhapp:layoutDescriptiontham 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>, một 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 biệt thông tin bố cục với nội dung mô tả chuyển động, mỗiMotionLayoutsẽ 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 sẽ được ưu tiên hơn mọi định nghĩa tương tự trongMotionLayout.Sau đây là ví dụ về tệp cảnh chuyển động 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ơ bản về chuyển động.-
motion:constraintSetStartvàmotion:constraintSetEndlà các tham chiếu đến đ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:durationchỉ định số mili giây cần thiết để hoàn tất chuyển động.
-
-
<OnSwipe>cho phép bạn tạo chế độ điều khiển bằng thao tác chạm cho chuyển động.-
motion:touchAnchorIdđề cập đến khung hiển thị mà người dùng có thể vuốt và kéo. -
motion:touchAnchorSidecó nghĩa là khung hiển thị đang được kéo từ phía bên phải. -
motion:dragDirectionđề cập đến 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 tăng lên khi khung hiển thị được kéo sang phải.
-
-
<ConstraintSet>là nơi bạn xác định các ràng buộc khác nhau mô tả chuyển động của bạn. 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ề nhiều phần tử mà một cảnh chuyển động hỗ trợ, hãy xem các ví dụ về MotionLayout.
-
Thuộc tính được 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à ranh giới, MotionLayout còn nội suy các thuộc tính sau:
alphavisibilityelevationrotation,rotationX,rotationYtranslationX,translationY,translationZscaleX,scaleY
Thuộc tính tuỳ chỉnh
Trong <Constraint>, bạn có thể dùng phần tử <CustomAttribute> để chỉ định một hiệu ứng 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 2 thuộc tính riêng:
motion:attributeNamelà bắt buộc và phải khớp với một đối tượng 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:customColorValuecho màu sắcmotion:customIntegerValueđối với số nguyênmotion:customFloatValuecho số thựcmotion:customStringValuecho chuỗimotion:customDimensioncho phương diệnmotion:customBooleancho giá trị boolean
Khi chỉ định một thuộc tính tùy chỉnh, hãy xác định các giá trị điểm cuối trong cả phần tử <ConstraintSet> bắt đầu và kết thúc.
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 khung hiển thị thay đổi trong quá trình chuyển động, 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:
<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 bổ sung của MotionLayout
Ngoài các thuộc tính trong ví dụ trước, MotionLayout còn có các thuộc tính khác mà bạn có thể muốn chỉ định:
app:applyMotionScene="boolean"cho biết 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 có hiển thị đường 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 quá trình chuyển đổi) đến1(kết thúc quá trình chuyển đổi).app:currentState="reference"cho phép bạn chỉ định mộtConstraintSetcụ thể.app:motionDebugcho phép bạn hiển thị thông tin gỡ lỗi bổ sung 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
- Các 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)