Giới thiệu
UI (User Interface) là cái nhìn đầu tiên khi mà người dùng vào ứng dụng của chúng ta. Vậy làm sao chúng ta thiết kế được UI bắt mắt và dễ tương tác, thân thiện với người dùng. Trong Android có hổ trợ cho chúng ta một số ViewGroup để giúp chúng ta thiết kế giao diện từ đơn giản đến phức tạp ví dụ như FrameLayout, RelativeLayout, LinearLayout, TableLayout… Và trong bài viết này tôi sẽ giới thiệu những ViewGroup được sử dụng nhiều nhất trong Android và phân tích ưu, nhược điểm của từng ViewGroup đó.
Hệ thống View trong Android
Trên đây là hệ thống một số view trong Android. Chúng ta thấy rằng các view trong Android đều được kế thừa từ class View. Và các bạn hãy để ý đến class ViewGroup có các class con là FrameLayout, RelativeLayout, LinearLayout chính là những ViewGroup mà chúng ta cùng tìm hiểu ngày hôm nay.
Ngoài ra để tìm hiểu các view cơ bản trong Android các bạn có thể tham khảo bài viết này.
Khái niệm ViewGroup
ViewGroup là một view chứa các view con trong nó và có nhiệm vụ layout (sắp sếp) các phần tử con theo thuật toán của ViewGroup đó, và chuyển giao event xuống cho các con trong nó.
ViewGroup có các phương thức quan trọng mà các bạn cần biết:
onMeasure
Phương thức này tính toán chiều width, height cho View. Sẽ được giới thiệu chi tiết ở bài viết Custom View trong Android.
onLayout
Phương thức có nhiệm vụ layout các phần tử con trong nó. Ví dụ tôi có 4 view con, tôi muốn layout mỗi view con nằm 4 góc, thì tôi sẽ sử dụng phương thức này.
Hai phương thức onMeasure và onLayout chỉ sử dụng nếu bạn muốn tạo ViewGroup layout các phần tử con theo ý mình.
getChildAt
Lấy ra view tại vị trí index của ViewGroup. Bản chất của ViewGroup lưu các con của nó trong một mảng.
addView
Thêm view con vào ViewGroup.
removeView
Remove view con ra khỏi ViewGroup.
Tạo ViewGroup
Các bạn có thể tạo ra ViewGroup để layout các view con theo ý của các bạn bằng cách extends ViewGroup và implement lại phương thức onLayout của ViewGroup.
Trong Android các ViewGroup được sử dụng nhiều nhất đó là:
- FrameLayout
- RelativeLayout
- LinearLayout
ViewGroup sử dụng nhiều trong Android
FrameLayout
FrameLayout là ViewGroup đơn giản nhất trong Android vì thời gian tính toán trong onLayout cho việc sắp xếp các view con khá nhanh. Mặc định bạn thêm một view vào FrameLayout thì các view sẽ nằm đè lên nhau.
Ví dụ 1 TextView nằm đè lên ImageView như dưới đây:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.nguyennghia.demo.MainActivity"> <FrameLayout android:layout_gravity="center" android:layout_width="200dp" android:layout_height="200dp"> <ImageView android:scaleType="fitCenter" android:src="@drawable/avatar" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:layout_marginLeft="3dp" android:layout_marginRight="3dp" android:textSize="18sp" android:textStyle="bold" android:layout_marginBottom="6dp" android:gravity="center_horizontal" android:layout_gravity="bottom|center_horizontal" android:background="#a9b4af" android:text="Founder Eitguide.com" android:layout_width="match_parent" android:layout_height="wrap_content" /> </FrameLayout> </FrameLayout> |
Kết quả:
Ngoài ra để định vị các view con trong FrameLayout chúng ta sử dung thuộc tính layout_gravity. Và có các giá trị sau:
Giá trị | Ý nghĩa |
left | Định vị view con nằm mép trái view cha. |
top | Định vị view con nằm mép trên view cha. |
right | Định vị view con nằm mép phải view cha. |
bottom | Định vi view con nằm mép dưới view cha. |
center | Định vị view con nằm chính giữa view cha. |
center_vetical | Định vị view con nằm chính giữa view cha theo thiều dọc |
center_horizontal | Định vị view con nằm chính giữa view cha theo chiều ngang. |
Ngoài ra các bạn cũng có thể “or” hai giá trị lại với nhau. Ví dụ muỗn định vị view con nằm ở góc bottom-right sẽ là:
1 2 3 |
layout_gravity="bottom|right" or layout_gravity="right|bottom" |
Và nhiều hơn nữa các bạn có thể thử.
Thuộc tính layout_gravity bạn có thể sử dụng được với LinearLayout.
Ưu điểm
FrameLayout là nhẹ nhất trong ba ViewGroup được sử dụng phổ biến (FrameLayout, RelativeLayout, LinearLayout).
Nhược điểm
FrameLayout không thể thiết kế được những giao diện phức tạp.
RelativeLayout
Nghe đến cái tên RelativeLayout chúng ta hình dung đến cái gì mang tính “tương đối”. Relative Layout sở hửu đầy đủ các tính năng của FrameLayout và có thêm tính năng đó là các view con có thể định vị vị trí tương đối với nhau.
Ví dụ tôi có màn hình đăng nhập như dưới đây:
Cùng phân tích xíu nhé:
- TextView username nằm trên.
- EditText username nằm dưới TextView username.
- TextView password nằm ngay dưới EditText usename
- EditText password nằm ngay dưới TextView TextView password.
Và RelativeLayout hổ trợ cho chúng ta tính tương đối đó. Chúng ta có thể định vị View này tương đối với kia bằng cách chỉ ra id của view mà nó dùng để xét vị trí tương đối.
Và dưới đây là mã xml thiết kế cho UI trên sử dụng RelativeLayout.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:layout_centerInParent="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin"> <TextView android:id="@+id/tv_username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Username" android:textSize="18sp" /> <EditText android:id="@+id/edt_username" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/tv_username" /> <TextView android:id="@+id/tv_password" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/edt_username" android:text="Password" android:textSize="18sp" /> <EditText android:id="@+id/edt_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/tv_password" android:inputType="textPassword"/> </RelativeLayout> </RelativeLayout> |
Các bạn thấy rằng ví dụ trên sử dụng thuộc tính layout_below và và chỉ ra id chúng ta thiết kết UI một các dễ dàng. Và dưới đây là một số thuộc tính thường dùng với RelativeLayout.
Thuộc tính | Ý nghĩa |
layout_below | Chỉ ra rằng view hiện tại sẽ nằm dưới view có id được chỉ ra. |
layout_above | Chỉ ra rằng view hiện tại sẽ nằm trên view có id được chỉ ra. |
layout_toLeftOf | View hiện tại sẽ nằm bên trái view có id được chỉ ra. |
layout_toRightOf | View hiện tại sẽ nằm bên phải view có id được chỉ ra. |
layout_alignTop | Định vị view hiện tại theo cạnh trên của view có id được chỉ ra. |
layout_alignRight | Định vị view hiện tại theo cạnh phải của view có id được chỉ ra. |
layout_alignLeft | Định vị view hiện tại theo cạnh trái của view có id được chỉ ra. |
layout_alignBottom | Định vị view hiện tại theo cạnh dưới của view có id được chỉ ra. |
RelativeLayout không có thuộc tính layout_gravity để định vị các con theo view cha. Đối với RelativeLayout chúng ta sử dụng những thuộc tính khác như sau:
Thuộc tính | Ý nghĩa |
layout_centerInParent | Định vị view hiện tại ở giữa view cha |
layout_centerVertical | Định vị view hiện tại ở giữa view cha theo chiều dọc. |
layout_centerHorizontal | Định vị view hiện tại ở giữa view cha theo chiều ngang. |
layout_alignParentTop | Định vị view hiện tại ở theo cạnh trên của view cha. |
layout_alignParentBottom | Định vị view hiện tại ở theo cạnh dưới của view cha. |
layout_alignParentRight | Định vị view hiện tại ở theo cạnh phải của view cha. |
layout_alignParentLeft | Định vị view hiện tại ở theo cạnh trái của view cha. |
Ưu điểm
Ưu điểm của RelativeLayout là chúng ta có thể thiết kế UI một cách linh hoạt hơn so với FrameLayout.
Nhược điểm
RelativeLayout có các nhược điểm sau đây:
- Thời gian tính toán để layout các phần tử con chậm hơn FrameLayout
- Khi view có Visibility = GONE hoặc remove ra khỏi RelativeLayout thì các view có tính tương đối với view này sẽ bị hỗn loạn.
LinearLayout
Và cuối cùng trong bài viết tôi muốn giới thiệu đến các bạn ViewGroup có tên là LinearLayout. LinearLayout là một ViewGroup tỏ ra khá mạnh mẽ trong Android và được sử dụng rất nhiều. Vậy nó có gì đặc biệt hơn so với FrameLayout và RelativeLayout.
Điểm đặc biệt của LinearLayout đó là các view con trong đó không nằm đè lên nhau mà một view con trong nó sẽ chiếm 1 vị trí không ai có thể chiếm giữ.
Để thay đổi chiều layout của LinearLayout chúng ta sử dụng thuộc tính orientation:
Layout theo chiều dọc
1 |
orientation="vertical" |
Layout theo chiều ngang
1 |
orientation="horizontal" |
Chúng ta cùng xem sau để hiểu về LinearLayout
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vetical"> <View android:background="#b95b5b" android:layout_width="match_parent" android:layout_height="50dp"/> <View android:background="#1b5827" android:layout_width="match_parent" android:layout_height="100dp"/> <View android:background="#0e203e" android:layout_width="match_parent" android:layout_height="50dp"/> <View android:background="#86051b" android:layout_width="match_parent" android:layout_height="50dp"/> </LinearLayout> |
Hình ảnh kết quả
Ví dụ layout theo chiều ngang
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <View android:background="#b95b5b" android:layout_width="50dp" android:layout_height="match_parent"/> <View android:background="#1b5827" android:layout_width="100dp" android:layout_height="match_parent"/> <View android:background="#0e203e" android:layout_width="50dp" android:layout_height="match_parent"/> <View android:background="#86051b" android:layout_width="50dp" android:layout_height="match_parent"/> </LinearLayout> |
Kết quả
LinearLayout sử dụng layout_weight
Trên đây là những tính năng cơ bản của LinearLayout và ngay dưới đây tôi sẽ giới thiệu một tính năng được sử dùng đùng để chia layout.
Chúng ta sử dụng thuộc tính layout_weight để xác định view đó muốn chiếm bao nhiêu trong view cha.
Ví dụ tôi muốn chia kích thước màn hình thành 2 phần.
Phần 1 chiếm 1 / 4 và tiếp tục chia phần này theo chiều ngang 4 phần bằng nhau.
Phần 2 chiếm 3 / 4 và tiếp tục chia phần này theo 4 phần bằng nay theo chiều dọc.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_weight="1" android:layout_width="match_parent" android:layout_height="0dp" android:orientation="horizontal"> <View android:background="#61afdf" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> <View android:background="#338350" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> <View android:background="#ba2f9b29" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> <View android:background="#5a3676" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> </LinearLayout> <LinearLayout android:layout_weight="3" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="0dp"> <View android:background="#533838" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="0dp" /> <View android:background="#a11e1e" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="0dp" /> <View android:background="#188b12" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="0dp" /> <View android:background="#89147b" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="0dp" /> </LinearLayout> </LinearLayout> |
Kết quả
Vẫn ví dụ trên nhưng tôi set visibility = GONE như dưới đây và xem lại kết quả:
Chúng ta thấy rằng lúc này phần thứ hai không phải chiếm 3/4 nữa mà chiếm toàn bộ màn hình. Bởi vì mặc định chúng ta không xác định giá trịn cho weightSum thì weightSum sẽ được tính bằng đúng tổng layout_weight của các view con.
Ví dụ trên phần thứ 2 có layout_weight = “3” nên weightSum= “3” vì vậy nó sẽ chiếm toàn bộ màn hình. Vì vậy để chắc chắn chúng ta nên xác định weightSum cho LinearLayout. Ví dụ trênn được sửa thành như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:weightSum="4"> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal" android:visibility="gone" android:weightSum="4"> <View android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="#61afdf" /> <View android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="#338350" /> <View android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="#ba2f9b29" /> <View android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="#5a3676" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="3" android:orientation="vertical" android:weightSum="4"> <View android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="#533838" /> <View android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="#a11e1e" /> <View android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="#188b12" /> <View android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="#89147b" /> </LinearLayout> </LinearLayout> |
LinearLayout có thuộc tính layout_gravity giúp bạn căn chỉnh các view con theo view cha giống như FrameLayout.
Ưu điểm
So với FrameLayout và RelativeLayout thì LinearLayout tỏ ra khá mạnh mẻ, chúng ta có thể chia được các phần khác nhau. Thích hợp thiết kế cho các loại màn hình khác nhau.
Nhược điểm
LinearLayout là ViewGroup được xem là phức tạp vì thời gian tính toán để layout các phần tử con bên trong nó khá lâu. Vì vậy khi thiết kế UI chúng ta nên cân nhắc và xét độ ưu tiên sử dụng ViewGroup là từ FrameLayout > RelativeLayout > Linearlayout.
Kết luận
Trên đây tôi đã giới thiệu cho các bạn các ViewGroup được sử dụng phổ biến nhất trong Android cũng như những kiến thức về ViewGroup. Hy vọng rằng bài viết sẽ giúp ích cho các bạn trong học tập cũng như công việc. Nếu có bất cứ thắc mắc nào các bạn có thể để lại bình luận ở dưới bài viết hoặc liên hệ fanpage Eitguide Android để được giải đáp.