Tìm Hiểu Các Layout Trong Android

Posted by

Được chỉnh sửa ngày 9/11/2017.

Chào mừng các bạn đến với bài viết bổ sung cho kiến thức còn khuyết của Bài 10. Nói là khuyết nhưng không hẳn là vậy, mình vẫn muốn giảm tải cho Các bài học theo chương trình, các bài học chính này sẽ mang đến cho các bạn một kiến thức tối thiểu đủ để thực hành. Các kiến thức đầy đủ hơn sẽ được dời qua phần Bài viết bổ sung, như vậy các bạn sẽ cảm thấy nhẹ nhàng hơn với bài học chính, và dễ truy cứu hơn ở các bài viết bổ sung. Ngoài ra thì blog của mình còn dành một phần riêng, đó là Học qua các project nhỏ, phần này được viết theo yêu cầu của các bạn, những người mang đến cho mình những câu hỏi, những ý tưởng, rồi từ đó mình làm lại thành một hướng dẫn nhỏ và để lên đây cho mọi người cùng tham khảo.

Quay lại chủ đề bài viết, thông qua Bài 10 các bạn đã biết rõ về 2 loại layout được sử dụng nhiều nhất hiện nay, đó là LinearLayoutRelativeLayout. Bài hôm nay chúng ta cùng nhắc lại (mà không nói kỹ) 2 layout đó và cùng xem tiếp những loại layout còn lại của Android nhé.

FrameLayout – Đơn Giản Nhưng Ít Dùng

FrameLayout được xây dựng ra khá đơn giản, chúng chỉ như một cửa sổ dành riêng trên màn hình để hiển thị MỘT thành phần đơn lẻ nào đó. Điều này có nghĩa là FrameLayout không “khéo” để có thể sắp xếp các thành phần con của nó theo một trật tự “xếp lớp” như với LinearLayout. Hay cho phép các thành phần con tự canh chỉnh vị trí của mình theo các “mối quan hệ” như với RelativeLayout. FrameLayout chỉ giỏi trong việc hiển thị một view, hoặc giả có nhiều view muốn để vào layout này thì nó cũng chỉ cho phép chúng xếp chồng lên nhau, hay neo vào một góc nào đó. Sự đơn giản này của FrameLayout làm cho chúng khó để có thể tạo nên một giao diện tốt tương thích với nhiều kích cỡ màn hình khác nhau trên thị trường.

Như vậy mục này chỉ nói lan man về FrameLayout mà không đi sâu với nó, để rồi sau này khi làm quen đến Fragment thì chúng ta lại nhắc đến FrameLayout một lần nữa, nhưng cũng chỉ thoảng qua vì rõ ràng vai trò của anh chàng này đơn giản chỉ là nơi để hiển thị một thành phần đơn lẻ, trong trường hợp đó thành phần đơn lẻ chính là Fragment. Hay bài viết về ScrollView cũng có nhắc đến FrameLayout. Các bạn chờ xem nhé.

LinearLayout – Sắp Xếp Các View Nằm Cạnh Nhau

LinearLayout đã được nói đến rất rất rất kỹ ở Bài 10 rồi nhé, các bạn hãy vào xem, mình có nói kỹ cả lý thuyết lẫn thực hành cho các bạn dễ hiểu nữa đó.

RelativeLayout – Sắp Xếp Các View Theo Mối Quan Hệ

Có thể nói RelativeLayout là layout được dùng nhiều nhất trong Android, vì sự thoải mái và linh động trong việc sắp xếp các view con của nó. Điểm trừ lớn nhất của RelativeLayout có lẽ ở chỗ bạn phải tạo và quản lý quá nhiều các ID cho các view, để chúng có thể định nghĩa vị trí thông qua việc canh chỉnh dựa trên các quan hệ với các ID đó.

RelativeLayout cũng được nói đến khá là kỹ trong Bài 10 luôn nhé, mời các bạn cùng xem.

TableLayout – Nghe Tên Là Biết Sẽ Liên Quan Đến Bảng

Bảng này không phải bảng viết đâu nhé, mà là bảng biểu với các dòng và cột. Nếu bạn là dân lập trình HTML, hoặc chí ít cũng biết chút đỉnh HTML, có thể bạn sẽ thích làm việc với bảng, layout dạng bảng này có tên là TableLayout.

Nhưng bạn nên cẩn thận, layout dạng bảng này lại rất ít dùng trong Android. Lý do thứ nhất, layout này được kế thừa từ ý tưởng xây dựng bảng của HTML, bạn phải định nghĩa ra các dòng, ở mỗi dòng bạn sẽ khai báo từng cột, điều này làm code của TableLayout sẽ bị rườm rà hơn so với các layout khác. Thứ hai, nếu muốn hiển thị bảng, LinearLayout hay RelativeLayout cũng giải quyết được, không tin ư, hãy cho mình một giao diện bảng nào đó, mình hiển thị giống vậy nhưng không phải TableLayout cho bạn xem. Thứ ba, nắm các quy tắc để canh chỉnh dòng-cột sao cho ưng ý sẽ hơi khó khăn cho người mới bắt đầu hơn các quy tắc của các layout khác.

Dù sao thì code của TableLayout cũng dễ đọc hơn, ít phải định nghĩa nhiều ID cho các view hơn.

Nếu như bạn cũng giống mình, tuy không thích layout này lắm nhưng cũng nên biết về nó, và bài viết hôm nay sẽ giúp các bạn hiểu về TableLayout.

Không có một cách nào để chia nhỏ bài học TableLayout này ra làm từng đề mục cụ thể như các layout khác, vậy bạn hãy cùng mình đi theo mạch xây dựng ví dụ sau nhé.

Khai Báo TableLayout

Về cơ bản TableLayout là con của LinearLayout, thật ư? Đúng vậy, vì vậy mình mới chắc nịch với bạn rằng không cần dùng TableLayout mà chỉ cần LinearLayout thôi cũng đủ xây dựng các giao diện dạng bảng là vậy.

Bạn bắt đầu khai báo một TableLayout như vầy.

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</TableLayout>

Quy Tắc Xây Dựng Dòng (Row) Và Cột (Column)

Dòng (row) là do bạn xây dựng, tùy theo yêu cầu thực tế của giao diện, bạn sẽ quyết định được mình cần bao nhiêu dòng cho bảng. Mỗi dòng sẽ nằm trong một cặp mở/đóng tag TableRow.

Mình ví dụ rằng bảng của chúng ta có hai dòng, vậy hãy khai báo như sau.

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
    <TableRow>
    </TableRow>
    
    <TableRow>
    </TableRow>

</TableLayout>

Rồi nhé, chúng ta đã tạo ra hai dòng rỗng. Bây giờ nếu bạn thêm các widget vào từng dòng, chúng sẽ là các cột (column) của dòng đó. Khi này Android sẽ bố trí các cột theo quy luật của nó.

Để cho bạn thấy quy luật tạo ra các cột của Android như nào, mình sẽ đặt vào dòng thứ nhất 2 widget, dòng thứ hai 3 widget như sau.

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TableRow>
        <TextView
            android:id="@+id/tv1_1"
            android:text="Name"
            android:layout_margin="4dp"/>
        <Button
            android:id="@+id/btn1_2"
            android:text="Click to see"
            android:layout_margin="4dp"/>
    </TableRow>

    <TableRow>
        <TextView
            android:id="@+id/tv2_1"
            android:text="Phone Number"
            android:layout_margin="4dp"/>
        <EditText
            android:id="@+id/et2_2"
            android:hint="Your number here"
            android:layout_margin="4dp"/>
        <TextView
            android:id="@+id/tv2_3"
            android:text="(required)"
            android:layout_margin="4dp"/>
    </TableRow>

</TableLayout>

Mới demo một tí mà bạn có thể thấy độ dài của các dòng code XML rồi đúng không nào.

Như bạn thấy thì khi các widget được để vào từng dòng, Android sẽ chia ra làm các cột tương ứng, vì dòng thứ nhất có 2 item, dòng thứ hai có 3 item, tổng kết lại bảng của chúng ta sẽ trông như có 2 dòng và 3 cột (mặc dù dòng thứ nhất bị khuyết một cột).

Layout - TableLayout demo

Bạn có thích cách sắp xếp các cột như mặc định này không? Dĩ nhiên là không rồi, mọi thứ trông như một mớ hỗn độn. Giả sử yêu cầu mong muốn rằng Button ở dòng thứ nhất phải dài hết không gian còn lại của dòng, tức là ô chứa Button đó phải có độ rộng là sự kết hợp không gian của 2 cột còn lại.

Đơn giản quá vì các widget ở trong TableLayout có thêm thuộc tính android:layout_span giúp chúng kết hợp (span) các cột với nhau. Vậy chúng ta hãy set giá trị layout_span cho Button như sau.

<Button
	android:id="@+id/btn1_2"
	android:text="Click to see"
	android:layout_margin="4dp"
	android:layout_span="2"/>

Kết quả của layout_span như sau.

Layout - TableLayout demo

Bạn chú ý là với TableLayout thì bạn sẽ không điều khiển kích cỡ của các widget theo android:layout_widthandroid:layout_height nữa. Thay vào đó là các thuộc tính dành cho cột mà chúng ta vừa làm quen trên đây.

Chúng ta tiếp tục với việc thay đổi yêu cầu giao diện. Giả sử bạn không muốn TextView “Phone Number” xuất hiện nữa, thay vào vị trí đó chính là EditText “Your number here”. Và TextView “(required)” vẫn ở dòng thứ hai nhưng phải nằm về phía phải so với Button ở dòng đầu tiên cơ.

Chúng ta cùng phân tích yêu cầu. Nếu như xem 2 widget ở dòng thứ nhất là 2 cột. Dòng thứ hai chúng ta bỏ 1 widget rồi thì còn 2 widget, cũng sẽ là 2 cột, nhưng như đã nói, item của dòng thứ hai mình lại muốn hiển thị như là cột thứ ba (vì nó nằm bên phải Button). Wow ý tưởng đã có rồi đó, làm sao set text “(required)” như là cột thứ ba chứ không phải mặc định của nó là cột thứ hai. Trong TableLayout có thuộc tính android:layout_column giúp chúng ta chỉ định thứ tự cột mà widget đó muốn, với 0 là cột đầu tiên. Như vậy với mong muốn này chúng ta sẽ chuyển đổi code như sau.

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TableRow>

        <TextView
            android:id="@+id/tv1_1"
            android:layout_margin="4dp"
            android:text="Name" />

        <Button
            android:id="@+id/btn1_2"
            android:layout_margin="4dp"
            android:text="Click to see" />
    </TableRow>

    <TableRow>

        <EditText
            android:id="@+id/et2_2"
            android:layout_margin="4dp"
            android:background="#FFFF00"
            android:hint="Your number here" />

        <TextView
            android:id="@+id/tv2_3"
            android:layout_column="2"
            android:layout_margin="4dp"
            android:background="#00FFFF"
            android:text="(required)" />
    </TableRow>

</TableLayout>

Dòng có layout_column được mình tô sáng lên trong code. Và khi đó giao diện mong muốn như sau.

Layout - TableLayout demo

Theo như vị trí của các widget bạn sẽ thấy chúng sắp xếp như những gì chúng ta muốn. Mình set background cho 2 widget ở dòng thứ hai cho bạn thấy rõ vị trí của chúng, hơn là để ý vào đường gạch đứt màu xanh của editor, các đường gạch đứt này có vẻ sai sai.

Một Dòng Mà Không Phải Một Dòng

Bạn nghĩ rằng TableLayout chỉ chứa các TableRow là các dòng chuẩn? Trước đây mình cũng nghĩ vậy, nhưng rồi phát hiện ra nếu bạn thêm một widget vào giữa các dòng (TableRow) đó, TableLayout sẽ xem như widget đó là một dòng chuẩn, với độ rộng của widget đó tương tự như độ rộng của một dòng trong bảng vậy.

Bạn hãy xem code như sau, mình chèn 2 TextView vào giữa các dòng để tạo nhãn cho từng dòng.

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="Row 1"
        android:textStyle="bold"
        android:background="#D2D2D2"/>

    <TableRow>

        <TextView
            android:id="@+id/tv1_1"
            android:layout_margin="4dp"
            android:text="Name" />

        <Button
            android:id="@+id/btn1_2"
            android:layout_margin="4dp"
            android:text="Click to see" />
    </TableRow>

    <TextView
        android:text="Row 2"
        android:textStyle="bold"
        android:background="#D2D2D2"/>

    <TableRow>

        <EditText
            android:id="@+id/et2_2"
            android:layout_margin="4dp"
            android:background="#FFFF00"
            android:hint="Your number here" />

        <TextView
            android:id="@+id/tv2_3"
            android:layout_column="2"
            android:layout_margin="4dp"
            android:background="#00FFFF"
            android:text="(required)" />
    </TableRow>

</TableLayout>

Khi đó giao diện sẽ trông như sau.

Layout - TableLayout demo

Dãn Ra (Stretch), Co Lại (Shrink), Và Thu Lại (Collapse)

Sự huyền diệu và phức tạp của TableLayout đến đây đã lộ rõ, và tin vui với các bạn rằng đây cũng là các thông tin cuối cùng dành cho TableLayout.

Qua các ví dụ trên đây bạn cũng thấy rằng khi bạn đặt các widget vào các dòng, thì các cột được tạo ra tương ứng, với chiều rộng của mỗi cột chính là chiều rộng của các widget. Bạn có thể sẽ nhìn thấy khoảng trống còn lại bên trong TableLayout khi các widget không chiếm đủ không gian rộng này. Hoặc có cột sẽ ra khỏi màn hình nếu bạn để quá nhiều widget vào trong một dòng.

Hãy cùng xem qua các thuộc tính bên dưới dành cho TableLayout (không phải cho view con như các ví dụ trên kia) giúp canh chỉnh các view con trông đẹp hơn nhé.

Dãn Ra (Stretch)

Để giải quyết các trường hợp không chiếm trọn không gian rộng, hoặc tràn ra khỏi màn hình trên, đầu tiên Android cho ra khái niệm android:stretchColumns (làm dãn cột). Khi này tham số truyền vào cho thuộc tính này chính là thứ tự của cột muốn làm dãn. Thứ tự đó có thể là thứ tự của một cột, hoặc nhiều cột cách nhau bằng dấu phẩy, hoặc tất cả các cột được định nghĩa bằng dấu sao (*). Cột nào được chỉ định stretch sẽ có chiều rộng dãn ra sao cho tổng chiều rộng các cột sẽ bằng chiều rộng của TableLayout.

Ví dụ sau mình cho cột đầu tiên của TableLayout bị dãn ra nhé.

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:stretchColumns="0">

</TableLayout>

Mình chỉ hiển thị code của TableLayout thôi nhé, các widget con của TableLayout này vẫn như ở ví dụ trước.

Layout - TableLayout demo

Bạn có để ý thấy cột thứ nhất được rộng ra hơn, trong khi các cột còn lại vẫn giữ quy luật cũ. Với sự nâng cấp nhỏ này, bảng của chúng ta trông đầy đặn hơn vì đã tận dụng hết chiều rộng của màn hình rồi phải không nào.

Hình ảnh sau là khi mình chỉ định android:stretchColumns=”0,1″, tham số có chứa 2 cột thay vì 1 như trên đây. Và cái kết.

Layout - TableLayout demo

Bạn có thấy sự khác biệt không? Tôi cá là bạn thấy có đấy. Bạn hãy thử với  android:stretchColumns=”*” để xem sự khác biệt khi tất cả các cột trong bảng bị dãn ra nhé.

Co Lại (Shrink)

Ngược lại hoàn toàn với dãn ra, thuộc tính co lại android:shrinkColumns sẽ làm một cột, nhiều cột, hoặc tất cả các cột co lại để đảm bảo tất cả các cột trong bảng đều nằm gọn trong không gian rộng của bảng. Khi này nếu widget có chứa text, chúng sẽ bị rớt xuống nhiều dòng để dành không gian rộng cho các widget khác.

Thuộc tính này rất hữu dụng khi mà bảng của bạn chứa quá nhiều cột mà bạn vẫn muốn chúng được hiển thị.

Các tham số truyền vào tương tự như ở android:stretchColumns, ở đây mình chỉ ví dụ với một tham số truyền vào là cột thứ 0, bạn xem thử code nhé.

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:shrinkColumns="0">

</TableLayout>

Và cái kết đã được báo trước.

Layout - TableLayout demo

Thu Lại (Collapse)

Thu lại sẽ làm cho một cột, hoặc nhiều cột trong bảng của bạn bị… biến mất. Nó giống với lệnh hide khi bạn dùng bảng trên excel vậy.

Thuộc tính cho chức năng này là android:collapseColumns, giá trị truyền vào là một hoặc nhiều cột (thuộc tính này không định nghĩa giá trị truyền vào là “*” đâu nhé).

Ví dụ sau mình ẩn cột thứ nhất trong bảng.

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:collapseColumns="0">

</TableLayout>

Và kết quả này là.

Layout - TableLayout demo

Còn một ý nhỏ cuối cùng của TableLayout nhưng nó không quan trọng lắm, đó là bạn có thể lồng TableLayout khác vào trong một dòng của TableLayout cha, để tạo ra giao diện phức tạp hơn, nhưng cách này được khuyến khích không nên làm vì nó phức tạp thật.

Bạn vừa cùng mình đi qua các layout được dùng thường xuyên hoặc quan trọng trong Android. Với các layout này, bạn có thể thiết kế bất cứ giao diện từ đơn giản đến phức tạp nào. Mình dự định nói luôn đến ScrollView nhưng sợ bài viết quá dài, vậy mình xin phép nói đến vấn đề này ở bài sau nhé. Và ConstraintLayout cũng sẽ không đủ để nói trong bài hôm nay, mình đã viết riêng layout đặc biệt này ở đây, bạn xem thêm nhé.

Dĩ nhiên trong Android cũng còn nhiều các layout khác chứ không riêng các layout ở bài viết này. Đơn cử có thể kể đến như AbsoluteLayout đã “chết yểu” khá lâu, hay các layout chuyên dụng khác dùng cho các component chuyên dụng của Android sẽ được nói đến sau. Chúng đều không quan trọng và không làm ảnh hưởng đến cách thiết kế giao diện của bạn.

Cảm ơn bạn đã đọc các bài viết của Yellow Code Books. Bạn hãy ủng hộ blog bằng cách:

Đánh giá 5 sao bên dưới mỗi bài nếu thấy thích.
Comment bên dưới mỗi bài nếu có thắc mắc.
Để lại địa chỉ email của bạn ở thanh bên phải để nhận được thông báo sớm nhất khi có bài viết mới.
Chia sẻ các bài viết của Yellow Code Books đến nhiều người khác.

Advertisements
Rating: 5.0. From 4 votes.
Please wait...

3 comments

Gửi phản hồi