Lập trình Android cơ bản

Bài 7: Layout trong Android : Phần 1

1. Tổng quan về layout trong Android

1.1  Định nghĩa và các các loại layout
Nếu bạn nào đã từng đã từng học thiết web thi hẳn đã biết muốn xây dựng một giao diện website thì ta sẽ phải dựng các layout bố cục cho trang web đó và Android cũng vậy ta cũng phải dùng các layout được Android cung cấp sẵn để chứa đựng và sắp xếp bố cục các view để tạo nên giao diện cho ứng dụng Android.
Layout là thành phần định nghĩa cấu trúc giao diện người dùng hay nói cách khác là thành phần quyết định đến giao diện của một màn hình trong ứng dụng Android. Layout hỗ trợ việc căn chỉnh các widget (Ví dụ: TextView, Button, hay EditText…) như chúng ta thấy trong các ứng dụng Android.
1.2 Các loại layout trong Android
Android đang hỗ trợ chúng ta 6 loại layout:
  1. RelativeLayout
  2. LinearLayout
  3. GridLayout
  4. TableLayout
  5. Framelayout
  6. ConstraintLayout.
Mỗi loại layout có một đặc tính cũng như cách sử dụng khác nhau, hôm nay chúng ta sẽ tìm hiểu lần lượt các loại layout.

2. LinearLayout

LinearLayout là loại layout sẽ sắp xếp các view theo chiều dọc hoặc ngang theo thứ tự của các view.
Đây là ViewGroup sẽ giúp các bạn sắp xếp các view con chứa bên trong theo dạng hàng ngay hoặc hàng dọc với nhau. Nhìn vào các hình ảnh dưới đây bạn sẽ hình dung được ngay công dụng của LinearLayout là gì liền.
Đây là ví dụ sắp xếp theo chiều ngang với thuộc tính 
android:orientation="horizontal"
Còn đây là nằm dọc với thuộc tính 
android:orientation="vertical"

2.1 Thuộc Tính Lực Hấp Dẫn (Gravity)

Mặc định thì các thành phần con bên trong LinearLayout sẽ được “hút” về start-top theo “lực hấp dẫn” mặc định
Thuộc tính android:gravity để căn chỉnh các View nằm ở vị trí nào trong LinearLayout, nó nhận các giá trị (có thể tổ hợp lại với ký hiệu |)
Giá trịThuộc tính
centerCăn ở giữa
topỞ phần trên
bottomPhần dưới
center_horizontalỞ giữa theo chiều ngang
center_verticalỞ giữa theo chiều đứng
 leftTheo cạnh trái
rightTheo cạnh phải
bottomCạnh dưới
Ví dụ android:gravity=”right|center”

2.2 Thuộc Tính Trọng Số (Weight)

Các View con trong LinearLayout có thể gán cho nó một giá trị trọng số bằng thuộc tính android:layout_weight ví dụ như: android:layout_weight="2"; android:layout_weight="1.5" ... . Nếu View không gán giá trị này coi như nó có trọng số bằng không.
Trường hợp LinearLayout không sử dụng đến thuộc tính android:weightSum.
Khi chúng ta muốn các view tự động full màn hình thì sử dụng android:weightSum.
ví dụ như khi muốn chia màn hình thành 5 phần bằng nhau, ta sử dụng thuộc tính weightSum như hình dưới.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_gravity="center"
    android:orientation="vertical"
    android:weightSum="5"
    android:gravity="center"
    tools:context=".View">

    <Button
        android:layout_weight="1"
        android:textSize="30dp"
        android:text="01"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <Button
        android:layout_weight="1"
        android:textSize="30dp"
        android:text="02"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <Button
        android:layout_weight="1"
        android:textSize="30dp"
        android:text="03"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <Button
        android:layout_weight="1"
        android:textSize="30dp"
        android:text="04"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <Button
        android:layout_weight="1"
        android:textSize="30dp"
        android:text="05"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

3. Relativelayout

RelativeLayout là một ViewGroup có hiển thị các View con ở các vị trí tương đối. Vị trí của mỗi View có thể được quy định liên quan đến các View anh em (như bên trái của hoặc bên dưới một View khác) hoặc ở các vị trí tương đối với khu vực cha RelativeLayout(chẳng hạn như sắp xếp ngay phía dưới, bên trái hoặc trung tâm).

3.1 Thuộc tính Gravity

Các View con khi đã định vị xong trong RelativeLayout, giả sử coi như tất cả các View con nằm vừa trong một đường biên chữ nhật, thì cả khối các View con này có thể dịch chuyển tới những vị trí nhất định trong RelativeLayout bằng thuộc tính: android:gravity, nó nhận các giá trị (có thể tổ hợp lại với ký hiệu | )
Giá trịÝ nghĩa
centerCăn ở giữa
topỞ phần trên
bottomPhần dưới
center_horizontalỞ giữa theo chiều ngang
center_verticalỞ giữa theo chiều đứng
leftTheo cạnh trái
rightTheo cạnh phải
bottomCạnh dưới

3.2 Định vị view con bằng view cha

Vị trí của View con trong RelativeLayout có thể thiết lập bằng cách chỉ ra mối liên hệ vị trí với view cha, như căn thẳng cạnh trái View cha với View con, căn thẳng cạnh phải View cha với View con… Các thuộc tính thực hiện chức năng này như sau:
Thuộc tínhÝ nghĩa
android:layout_alignParentBottomtrue căn thẳng cạnh dưới view con với cạnh dưới View cha
android:layout_alignParentLefttrue căn thẳng cạnh trái view con với cạnh trái View cha
android:layout_alignParentRighttrue căn thẳng cạnh phải view con với cạnh phải View cha
android:layout_alignParentToptrue căn thẳng cạnh trên view con với cạnh trên View cha
android:layout_centerInParenttrue căn view con vào giữa View cha
android:layout_centerHorizontaltrue căn view con vào giữa View cha theo chiều ngang  
android:layout_centerVerticaltrue căn view con vào giữa View cha theo chiều đứng

3.3 Định vị các view con với nhau bằng thuộc tính liên hệ với nhau

Tất cả các thuộc tính dưới đây cần phải truyền vào một ID @+id/
  1. android:layout_alignTop – Chỉ định đỉnh của thành phần này sẽ được canh theo đỉnh của thành phần gọi đến bằng ID.
  2. android:layout_alignBottom – Chỉ định đáy của thành phần này sẽ được canh theo đáy của thành phần gọi đến bằng ID.
  3. android:layout_alignStart – Chỉ định cạnh start của thành phần này sẽ được canh theo cạnh start của thành phần gọi đến bằng ID.
  4. android:layout_alignEnd – Chỉ định cạnh end của thành phần này sẽ được canh theo cạnh end của thành phần gọi đến bằng ID.
  5. android:layout_alignBaseline – Chỉ định baseline của thành phần này sẽ được canh theo baseline của thành phần gọi đến bằng ID. Baseline này bạn không nhìn thấy được, dùng để canh chỉnh cho text hiển thị bên trong widget, do đó sẽ hữu dụng khi canh chỉnh các TextView với nhau).
  6. android:layout_above – Chỉ định thành phần này sẽ nằm ở trên so với thành phần gọi đến bằng ID.
  7. android:layout_below – Chỉ định thành phần này sẽ nằm dưới so với thành phần gọi đến bằng ID.
  8. android:layout_toStartOf – Chỉ định thành phần này sẽ nằm bên phía start so với thành phần gọi đến bằng ID.
  9. android:layout_toEndOf – Chỉ định thành phần này sẽ nằm bên phía end so với thành phần gọi đến bằng ID.
  10. android:layout_toLeftOf – Chỉ định thành phần này sẽ nằm bên phía trái so với thành phần gọi đến bằng ID.
  11. android:layout_toRightOf – Chỉ định thành phần này sẽ nằm bên phía phải so với thành phần gọi đến bằng ID.
Ví dụ:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_gravity="center"
    android:gravity="center"
    tools:context=".View">


    <TextView
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:text=" Hop 1"
        android:textColor="@android:color/black"
        android:id="@+id/hop1"
        android:textSize="10pt"
        android:textAlignment="center"
        android:background="#D32F2F"
        />
    <TextView
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:text=" Hop 2"
        android:textColor="@android:color/black"
        android:id="@+id/hop2"
        android:textSize="10pt"
        android:textAlignment="center"
        android:layout_toRightOf="@+id/hop1"
        android:background="#FFEB3B"
        />
    <TextView
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:text=" Hop 3"
        android:textColor="@android:color/black"
        android:id="@+id/hop3"
        android:background="#FFAB40"
        android:textSize="10pt"
        android:textAlignment="center"
        android:layout_below="@+id/hop1"
        />
    <TextView
        android:layout_width="150dp"
        android:layout_height="50dp"
        android:text="Hop 4"
        android:textColor="@android:color/black"
        android:id="@+id/hop4"
        android:textSize="10pt"
        android:textAlignment="center"
        android:background="#E040FB"
        android:layout_below="@+id/hop2"
        android:layout_toRightOf="@+id/hop3"
        />




</RelativeLayout>

4. GridLayout

GridLayout sử dụng một mạng lưới các dòng mỏng và vô hạn để tách khu vực bản vẽ của nó thành: các hàng, các cột, và các ô (cell). Nó hỗ trợ cả việc bắc qua (span) các hàng và các cột, nghĩa là cho phép hợp nhất ô gần nhau thành một ô lớn (hình chữ nhật) để chứa một View.

GridLayout trong Android

GridLayout sử dụng một mạng lưới các dòng mỏng và vô hạn để tách khu vực bản vẽ của nó thành: các hàng, các cột, và các ô (cell). Nó hỗ trợ cả việc bắc qua (span) các hàng và các cột, nghĩa là cho phép hợp nhất ô gần nhau thành một ô lớn (hình chữ nhật) để chứa một View.
Kích thước (Size), Căn lề (Margin) và Căn chỉnh/trọng lực (Alignment/Gravity)
Trong GridLayout, việc chỉ định kích thước và căn lề làm giống với LinearLayout. Căn chỉnh/trọng lượng (Alignment/gravity) cũng làm việc giống như trọng lực (gravity) trong LinearLayout và sử dụng chung các hằng số: left, top, right, bottom, center_horizontal, center_vertical, center, fill_horizontal, fill_vertical và fill.
Tính linh hoạt (Flexibility)
Không giống như hầu hết các lưới ở các bộ công cụ khác, Android GridLayout không liên kết dữ liệu với các hàng hoặc cột. Thay vào đó, tất cả mọi thứ được làm với Aligment (căn chỉnh) và sự linh hoạt được liên kết với các thành phần tự thân của nó. Sự linh hoạt của các cột được suy ra từ thuộc tính gravity (trọng lực) của các thành phần bên trong các cột. Nếu mọi thành phần định nghĩa một gravity, cột được coi là linh hoạt, nếu không cột được coi là không linh hoạt
GridLayouts trong tập tin XML Resource 
Một GridLayout  được khai báo bên trong thẻ . Ví dụ:
số dòng và cột trong lưới có thể được khai báo bằng cách sử dụng thuộc tính android: rowCount và android: columnCount.
Tương tự, hướng hiển thị của GridLayout có thể tùy ý được xác định thông qua thuộc tính android: orientation.
Ví dụ sau XML tuyên bố một cấu hình 3 x 3 GridLayout theo hướng ngang:
<?xml version="1.0" encoding="utf-8"?>
<GridLayout 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:layout_gravity="center"
    android:orientation="vertical"
    android:id="@+id/gridlayout_demo"
    android:gravity="center"
    android:columnCount="2"
    android:rowCount="2"
    tools:context=".View">
   
</GridLayout>
Thêm View cho GridLayouts
Các Views có thể được thêm vào GridLayout bằng cách khai báo các phần tử bên trong cấu trúc  trong tập tin XML. Nếu không có giá trị hàng và cột nào được khai báo cho một View thì nó được định vị tự động bởi lớp GridLayout dựa trên cấu hình của Layout và vị trí của khung nhìn trong tập tin XML. XML sau đây đặt bốn nút trong GridLayout, với mỗi View được đặt từ góc trái của ô.
Trong ví dụ sau chúng ta đặt 5 Button lên GridLayout có 3 dòng, 3 cột. Các View được đặt ở dòng 0 và dòng 2.
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/GridLayout1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:columnCount="3"
    android:orientation="horizontal"
    android:rowCount="3" >
    <Button
        android:id="@+id/button1"
        android:layout_gravity="left|top"
        android:text="@string/button_name" />
    <Button
        android:id="@+id/button4"
        android:layout_column="0"
        android:layout_gravity="left|top"
        android:layout_row="2"
        android:text="@string/button_name" />
    <Button
        android:id="@+id/button5"
        android:layout_width="213dp"
        android:layout_column="1"
        android:layout_columnSpan="2"
        android:layout_gravity="fill_horizontal|fill_vertical"
        android:layout_row="2"
        android:text="@string/button_name" />
    <Button
        android:id="@+id/button2"
        android:layout_column="2"
        android:layout_gravity="left|top"
        android:layout_row="0"
        android:text="@string/button_name" />
    <Button
        android:id="@+id/button3"
        android:layout_column="2"
        android:layout_gravity="right|top"
        android:layout_row="0"
        android:text="@string/button_name" />
</GridLayout>