Lập trình Android – Bài 4: Thiết kế giao diện với RelativeLayout

Như mình đã nói ở các bài trước: Thiết kế giao diện tốt thì bạn học Android tốt, thiết kế giao diện dở thì bạn học Android dở. Vì vậy hôm nay chúng ta bắt đầu đi vào thực hành thiết kế giao diện.

[qads]

1. Tổng quan View

Trước tiên mình xin giới thiệu qua một chút với các bạn về giao diện Android. Các bạn quan sát hình sau:
view-android

Tất cả các thành phần hiển thị đều được gọi là View và thực tế chúng kế thừ từ class View. View nghĩa là hiển thị. Trong View chúng ta phân làm 2 loại là:

  • View đơn: là những thành phần hiển thị hiện hữu mà chúng ta có thể nhìn thấy trực tiếp như TextView, EditText, Button.
  • ViewGroup: là View để chứa các view khác, có thể chứa view đơn hoặc chứa ViewGroup khác.

Trong ViewGroup chúng ta có rất nhiều loại, ở đây mình giới thiệu tới các bạn 2 loại thường xuyên dùng nhất là RelativeLayout và LinearLayout.

  • RelativeLayout là ViewGroup chứa các View khác và quản lý theo mối quan hệ giữa các View nằm trong nó. Giống như bạn A ngồi bên cạnh bạn B, bạn C ngồi bên dưới bạn B,…
  • LinearLayout là ViewGroup chứa các View khác và quản lý theo chiều ngang hoặc chiều dọc (tùy ta quy định). Giống như chúng ta xếp hàng vậy, xếp theo hàng ngang hoặc hàng dọc.

Bài hôm nay chúng ta sẽ đi tìm hiểu RelativeLayout qua việc thực hành thiết kế giao diện của một số ứng dụng.
Các bạn tạo project mới và vào tab Text của file activity_main.xml để thực hiện nhé.

2. Thiết kế giao diện Login với RelativeLayout

Chúng ta hình dung giao diện Login như sau:

android-login

Như vậy, chúng ta sẽ cần 3 TextView (Login, user, password), 2 EditText (user, password) và 1 Button (ok). Chúng ta tạm đặt cho chúng ta tvLogin, tvUser, tvPassword, editUser, editPassword, btnOk.
Do chúng ta đang sử dụng RelativeLayout, như bên trên mình nói, RelativeLayout sắp xếp các thành phần bên trong nó dựa và mối quan hệ giữa chúng. Ta hình dung tiếp:

  • tvLogin ở trên đầu
  • tvUser dưới tvLogin
  • editUser dưới tvUser
  • tvPassword dưới editUser
  • editPassword dưới tvPassword
  • btnOk dưới editPassword

Vậy chúng ta sẽ có code như sau:

<?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">

    <TextView
        android:id="@+id/tvLogin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="Login"
        android:textSize="24sp" />

    <TextView
        android:id="@+id/tvUser"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tvLogin"
        android:text="user" />

    <EditText
        android:id="@+id/editUser"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tvUser" />

    <TextView
        android:id="@+id/tvPassword"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/editUser"
        android:text="password" />

    <EditText
        android:id="@+id/editPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tvPassword" />

    <Button
        android:id="@+id/btnOk"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/editPassword"
        android:layout_centerHorizontal="true"
        android:text="ok" />

</RelativeLayout>

Mình giải thích về code như sau. Do đây là lần đầu tiên mình giải thích code xml nên các bạn chú ý. Các dòng android:xyz nằm trong các thẻ View tương ứng được gọi là các thuộc tính của View đó.

Trước tiên các bạn nhìn vào thẻ RelativeLayout đầu tiên

Vì RelativeLayout là một ViewGroup nên nó có thẻ đóng (dòng 2) và thẻ mở (dòng 48) và nó chứa các phần tử con nằm trong 2 cặp thẻ đóng mở này. Các thuộc tính của nó đã dùng là

android:layout_width và android:layout_height đây 2 là thuộc tính chỉ chiều ngang và chiều dọc của nó. Mọi View đều bắt buộc có ít nhất 2 thuộc tính này để xác định kích thước của View đó. Nếu View nào không có 1 trong 2 thuộc tính này sẽ bị lỗi. Giá trị của 2 thuộc tính này có thể nhận là:

– wrap_content : nghĩa là vừa đủ nội dung (wrap – vừa đủ, content – nội dung). Tức là nội dung của nó có bao nhiêu thì nó vừa đủ đến đó.
– match_parent : nghĩa là toàn bộ của cha nó (match – toàn bộ, parent – cha mẹ). Tức là cha nó (thằng chứa nó) có bao nhiêu thì nó lấy hết phần đó.
– xdp : trong đó x là 1 số thực, dp là đơn vị độ dại giống như cm, m, inch,.. Trong Android đơn vị độ dài tới thời điểm này các bạn nhớ nó là dp.
Đối với ViewGroup RelativeLayout này, chúng ta đặt cả chiều ngang và chiều dọc đều là match_parent tức là chiều ngang và chiều dọc đều lấy hết cha nó, cha nó chính là cái màn hình điện thoại.

Tiếp theo, các bạn chú ý tới thẻ TextView đầu tiên, tvLogin
Tại đây 2 thuộc tính android:layout_width và android:layout_height là đương nhiên và bắt buộc có. Mình làm rõ một chút để các bạn hiểu thêm:
Chiều ngang mình đặt là wrap_content – vừa đủ nội dung, tức là toàn bộ nó luôn vừa đủ nội dung. Các bạn click chuột vào nó sẽ thấy viền xanh bao quanh, nó luôn vừa với nội dung
android-wrap-content
Nếu các bạn đặt giá trị cho nó là android:layout_width=”match_parent” tức là chiều ngang bạn đã cho nó bằng toàn bộ chiều ngang thằng cha, cha nó là thằng RelativeLayout mà thằng này đang chiếm toàn bộ chiều ngang màn hình nên nó có chiều ngang toàn bộ màn hình như này.
android-match-parent

– Thuộc tính android:layout_centerHorizontal=”true” tức là chúng ta đặt nó nằm chính giữa theo chiều ngang của thằng cha. center – chính giữa, horizontal – chiều ngang. Vì vậy các bạn sẽ thấy tvLogin ở chính giữa màn hình. Nếu các bạn đặt chiều ngang là match_parent (tức toàn bộ màn hình) thì cái layout của nó sẽ ở giữa và coi như không đổi gì (vì nó là toàn bộ chiều ngang, nó lại chính giữa mà) và text “Login” nằm bên trái chữ không phải giữa nữa. Các bạn phân biệt 1 View có 2 thành phần là nó và nội dung của nó. Với TextView thì nó là layout bao quanh text, nội dung của nó là text. Với RelativeLayout thì nó chính là phần khung bao bọc, nội dung của nó là các thành phần con bên trong nó. Vì vậy trong trường hợp này khi các bạn cho chiều ngang của tvLogin là match_parent mà muốn cho text cũng ở giữa thì bạn phải dùng thuộc tính android:gravity=”center”. android:gravity để định nghĩa vị trí nội dung của View.
Cụ thể khi đó TextViewLogin sẽ nhưa sau:

<TextView
    android:id="@+id/tvLogin"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:gravity="center"
    android:text="Login"
    android:textSize="24sp" />

– Thuộc tính android:textSize=”24sp” tức là chúng ta đặt cỡ chữ cho nó là 24sp. Đơn vị của cỡ chữ là sp.

Tiếp đến EditText editUser và các View bên dưới

Chúng đều tương tự nhau và đều có 1 thuộc tính là:

android:layout_below : nghĩa là bên dưới của cái gì đó. Bên dưới của cái gì đó được xác định bằng id của view liên quan đến nó.

Ngoài ra các bạn cần biết thêm các thuộc tính tương tự của View có thể dùng trong RelativeLayout

  • android:layout_above : Nằm bên trên một view nào đó (đối số là id của view)
  • android:layout_toLeftOf : Nằm bên trái của View nào đó (đối số là id của view)
  • android:layout_toRightOf: Nằm bên phải của View nào đó (đối số là id của view)
  • android:layout_alignParentTop, android:layout_alignParentRight, android:layout_alignParentBottom, android:layout_alignParentLeft : các thuộc tính chỉ định nằm trên, phải, dưới, trái của View cha. Đối số của chúng là true, false.

3. Thiết kế giao diện Chat với RelativeLayout

Giao diện Chat chúng ta đang nói đến nó như giao diện của ứng dụng Messager Facebook đó. Tức là sẽ có 2 người chat với nhau. Như vậy các bạn hình dung giao diện sẽ như sau:
android-chat-layout
Theo hình trên, chúng ta cần 1 ListView (đây là View cho phép hiển thị một danh sách dữ liệu), 1 EditText và 1 ImageButton là button mà có ảnh. Chúng ta đặt id cho chúng lần lượt là lvMessage, editMessage, btnSend.

  • btnSend nằm tít bên dưới màn hình và nằm tít bên phải màn hình
  • editMessage cũng nằm tít bên dưới của màn hình và nằm bên trái của btnSend.
  • lvMessage nằm bên trên editMessage.

Bây giờ các bạn tạo 1 file giao diện mới bằng cách click chuột phải vào thư mục layout nằm trong res và chọn new -> layout resource file và đặt tên file là layout_chat.xml

create-xml-layout

Tiếp theo các bạn tạo 1 icon cho button send như sau. Click chuột phải vào thư mục drawable trong res
chọn new -> vector Asset. Hộp thoại hiện ra các bạn click button Choose.
anndroid-create-icon

Một hộp thoại khác hiện ra rất nhiều icon, các bạn kéo xuống khoảng 2/3 và chọn icon send:
android-create-icon-send

Click OK, và quay về đổi tên icon là ic_send

android-rename-icon

Cuối cùng Click next -> Finish. bây giờ icon đã được tạo ra trong thư mục drawable, thực chất nó được vẽ bằng xml.

Giờ mở tab Text của layout_chat.xml ra. Các bạn sẽ thấy mặc định có LinearLayout, các bạn sửa thành RelativeLayout và viết code như sau:

<?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"
    android:orientation="vertical">

    <ListView
        android:id="@+id/lvMessage"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/editMessage" />

    <EditText
        android:id="@+id/editMessage"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_toLeftOf="@+id/btnSend" />

    <ImageButton
        android:id="@+id/btnSend"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:src="@drawable/ic_send" />

</RelativeLayout>

Các thuộc tính trong code này mình đã giải thích, duy chỉ có thuộc tính android:src nghĩa là đường dẫn đến file icon. giá trị ở đây là @drawable/ic_send tức là lấy file ic_send nằm trong thư mục drawable.

android-chat-listview

Một điều chú ý nữa là giao diện xem trước các bạn sẽ thấy ListView được mô tả như thế này. Đó là mô tả khi list chứa các phần tử nhưng khi chạy ứng dụng bạn sẽ thấy list trống, vì chúng ta chưa có dữ liệu. Sau này chúng ta sẽ làm việc với nó sau nhé. Bài này chỉ thiết kế giao diện thôi.

Đến đây các bạn chạy chương trình thì sẽ vẫn hiển thị giao diện Login chúng ta làm bàn đầu, để thay đổi giao diện Chat thì bạn cần vào file MainActivity.java đổi setContentView(R.layout.activity_main); thành setContentView(R.layout.layout_chat); Vậy là xong.

Bài hôm nay hơi dài chút nhưng mình đặt rất nhiều hi vọng. Thiết kế tốt thì lập trình tốt. Chúc các bạn học tập hiệu quả. Nếu có thắc mắc góp ý, chia sẻ vui lòng để lại bình luận bên dưới bài viết.