ConstraintLayout trong Android
ConstraintLayout là một layout mạnh, khuyến khích bạn dùng nếu có thể vì nó giúp tạo ra các giao diện phức tạp, mềm dẻo (hạn chế tối đa sử dụng các layout lồng nhau). Nó giúp định vị, sắp xếp các View con dựa trên sự ràng buộc liên hệ của các View con với View cha và sự liên hệ ràng buộc giữa các View con với nhau, với cơ chế tạo xích các View, gán trọng số hay sử dụng trợ giúp giao diện với Guideline.
ConstraintLayout thuộc Libaray Support nên để tích hợp vào dự án hãy thêm vào Gradle phiên bản muốn dùng, ví dụ:
implementation 'com.android.support:appcompat-v7:27.1.0' implementation 'com.android.support.constraint:constraint-layout:1.0.2'
Sự ràng buộc
Mỗi view trong ConstraintLayout để định vị được chính xác cần tối thiếu 2 ràng buộc, một theo phương ngang (X) và một theo phương đứng (Y)
Khái niệm ràng buộc giữa các phần tử ở đây ám chỉ sự liên kết với nhau của các phần tử với nhau (kể cả với phần tử cha ConstraintLayout), sự căn chỉnh phần tử theo phần tử khác, hoặc với những đường thẳng ẩn thêm vào. Mỗi ràng buộc của phần tử View sẽ hoặc hưởng đến vị trí của nó theo trục X hoặc trục Y. Các View không có ràng buộc sẽ định vị ở góc trái - trên (tọa độ 0,0).
Trước tiên tham khảo bảng các thuộc tính về ràng buộc layout_constraint ... , các thuộc tính ràng buộc sử dụng với namespace:app
, giá trị nó gán vào là một ID của phần tử khác để kết nối ràng buộc hoặc là phần tử ch bằng hằng số "parent"
, ví dụ:
app:layout_constraintBottom_toBottomOf="parent"
Ràng buộc | Ý nghĩa ràng buộc |
---|---|
layout_constraintLeft_toLeftOf |
Rang buộc cạnh trái của phần tử tới phần tử chỉ ra trong giá trị (gán ID) |
layout_constraintLeft_toRightOf |
Bên trái với bên phải của phần tử chỉ ra |
layout_constraintRight_toLeftOf |
Bên phải với bên trái |
layout_constraintRight_toRightOf |
Phải với phải |
layout_constraintTop_toTopOf |
Cạnh trên với cạnh trên |
layout_constraintTop_toBottomOf |
Cạnh trên nối với cạnh dưới |
layout_constraintBottom_toTopOf |
Dưới với trên |
layout_constraintBottom_toBottomOf |
Dưới với dưới |
layout_constraintBaseline_toBaselineOf |
Trùng Baseline |
layout_constraintStart_toEndOf |
Bắt đầu - Kết húc |
layout_constraintStart_toStartOf |
Bắt đầu - Bắt đầu |
layout_constraintEnd_toStartOf |
Cuối với bắt đầu |
layout_constraintEnd_toEndOf |
Cuối với cuối |
Thuộc tính Margin trong các phần tử con
Cạnh nào của View con có ràng buộc thì có thể thiết lập thêm thuộc tính Margin để điều chỉnh thêm khoảng cách các cạnh tới điểm nối ràng buộc.
Các thuộc tính margin theo các cạnh: android:layout_marginStart, android:layout_marginEnd, android:layout_marginLeft, android:layout_marginTop, android:layout_marginRight, android:layout_marginBottom
Tương tự có layout_goneMarginStart, layout_goneMarginEnd, layout_goneMarginLeft, layout_goneMarginTop, layout_goneMarginRight, layout_goneMarginBottom có hiệu lực khi đối tượng ràng buộc đến gone
Phần tử Guideline
Ta có thể một đường kẻ ẩn trong ConstraintLayout nằm ngang hoặc đứng nó như là một View con để các View khác ràng buộc đến nếu muốn. Thêm vào bằng cách:
<android.support.constraint.Guideline android:id="@+id/guideline_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.3" />
Thiết lập đó là được kẻ ngang bằng thuộc tính: android:orientation="horizontal"
đường kể đứng android:orientation="vertical"
Vị trí phân chia ContraintLayout của GuideLine
1 Vị trị của Guideline có thể thiết lập nó cách cạnh trái (hoặc trên nếu là Guideline ngang) bằng thuộc tính app:layout_constraintGuide_percent
giá trị là tỷ lệ phần trăm như 0.5 (50%), 0.2 (20%) độ rộng (cao) của ConstraintLayout. Ví dụ: app:layout_constraintGuide_percent="0.1"
Ví dụ:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout 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" tools:context=".MainActivity"> <android.support.constraint.Guideline android:id="@+id/guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.3" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:text="Button1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintStart_toStartOf="@+id/guideline" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="20dp" android:text="BUTTON2" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="@+id/guideline" app:layout_constraintTop_toBottomOf="@+id/button" /> </android.support.constraint.ConstraintLayout>
2 Nếu không muốn sử dụng layout_constraintGuide_percent
thì có thể sử dụng cách thiết lập Guideline cách cạnh bắt đầu (trên với Guidleline ngang) bao nhiêu bằng thuộc tính: app:layout_constraintGuide_begin
ví dụ:
app:layout_constraintGuide_begin="100dp"
Hoặc thiết lập cách cạnh cuối bao nhiêu với layout_constraintGuide_end
Bias
Khi hai cạnh đối diện nhau của View có ràng buộc, thì hai dàng buộc này ứng xử như một liên kết lò xo mặc định nó có độ mềm (độ cứng) bằng nhau dẫn đến View sẽ nằm giữa 2 điểm neo của ràng buộc. Nếu muốn điều chỉnh độ cứng này thì sử dụng thuộc tính:
app:layout_constraintVertical_bias
thiết lập độ mềm của ràng buộc đầu (ngang). Với tổng độ mềm là 1 thì khiapp:layout_constraintVertical_bias="0.1"
thì độ mềm ràng buộc thứ hai sẽ là0.9
layout_constraintHorizontal_bias
để thiết lập độ mềm hai ràng buộc theo phương đứng
Tỷ lệ các cạnh của View
Khi View con có thiết lập tối thiểu một kích thước là "0dp" thì kích thước đó có thể tự động điều chỉnh bằng cách lấy theo tỷ lệ với cạnh còn lại, thuộc tính app:layout_constraintDimensionRatio
cho phép gán tỷ lệ giữa chiều rộng và chiều cao, ví dụ: app:layout_constraintDimensionRatio="2:1"
chiều rộng gấp đôi chiều cao
Chain - xích các View lại
Các View ràng buộc qua lại các cạnh tiếp giáp nhau sẽ tạo thành một xích các View. Có hai loại xích các phần tử theo phương ngang và theo phương đứng. Lúc đó, phần tử đầu tiên có chức năng thiết lập chung một số thông số về xích.
Một xích theo phương ngang
Phần tử đầu của xích thiết lập kiểu xích bằng thuộc tính: app:layout_constraintHorizontal_chainStyle
và app:layout_constraintVertical_chainStyle
tùy theo xích đứng hay ngang, mặc định xích có kiểu spread
xích "spread": app:layout_constraintHorizontal_chainStyle="spread" hoặc app:layout_constraintVertical_chainStyle="spread"
Ví dụ: (2 xích ngang và đứng)
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout 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" tools:context=".MainActivity" tools:layout_editor_absoluteY="81dp"> <Button android:id="@+id/b1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#1eb729" android:text="B1 - HEAD" app:layout_constraintBottom_toTopOf="@id/b5" app:layout_constraintHorizontal_chainStyle="spread" app:layout_constraintRight_toLeftOf="@id/b2" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/b4" /> <Button android:id="@+id/b2" android:text="B2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toRightOf="@id/b1" app:layout_constraintRight_toLeftOf="@id/b3" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/b3" android:text="B3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintLeft_toRightOf="@id/b2" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/b4" android:text="B4 - HEAD" android:textColor="#cf3131" app:layout_constraintBottom_toTopOf="@id/b1" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="@id/b1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/b5" android:text="B5" app:layout_constraintTop_toBottomOf="@id/b1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="@id/b1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </android.support.constraint.ConstraintLayout>
xích "packed": app:layout_constraintHorizontal_chainStyle="packed" hoặc app:layout_constraintVertical_chainStyle="packed"
xích "spread_inside": app:layout_constraintHorizontal_chainStyle="spread_inside" hoặc app:layout_constraintVertical_chainStyle="spread_inside"
Với loại spread_inside và spread theo phương của xích các phần tử có thể gán kích thước bằng 0 và điều chỉnh lại theo trọng số weight với ý nghĩa tương tự như LinearLayout, thuộc tính thiết lập trọng số là: app:layout_constraintHorizontal_weight và app:layout_constraintVertical_weight
Ví dụ:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout 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" tools:context=".MainActivity" tools:layout_editor_absoluteY="81dp"> <Button android:id="@+id/b1" android:layout_width="wrap_content" android:layout_height="0dp" android:textColor="#1eb729" android:text="B1 - HEAD" app:layout_constraintBottom_toTopOf="@id/b5" app:layout_constraintHorizontal_chainStyle="spread_inside" app:layout_constraintRight_toLeftOf="@id/b2" app:layout_constraintStart_toStartOf="parent" app:layout_constraintHorizontal_weight="1" app:layout_constraintVertical_weight="2" app:layout_constraintTop_toBottomOf="@id/b4" /> <Button android:id="@+id/b2" android:text="B2" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toRightOf="@id/b1" app:layout_constraintRight_toLeftOf="@id/b3" app:layout_constraintHorizontal_weight="2" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/b3" android:text="B3" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_weight="3" app:layout_constraintLeft_toRightOf="@id/b2" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/b4" android:text="B4 - HEAD" app:layout_constraintVertical_chainStyle="spread_inside" android:textColor="#cf3131" app:layout_constraintBottom_toTopOf="@id/b1" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="@id/b1" app:layout_constraintVertical_weight="1" android:layout_width="wrap_content" android:layout_height="0dp" /> <Button android:id="@+id/b5" android:text="B5" app:layout_constraintTop_toBottomOf="@id/b1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="@id/b1" android:layout_width="wrap_content" app:layout_constraintVertical_weight="3" android:layout_height="0px" /> </android.support.constraint.ConstraintLayout>