Android – Thiết kế giao diện người dùng

Rate this post

Giao diện người dùng của một ứng dụng Android được xây dựng bằng các đối tượng ViewViewGroup. View là các đối tượng như button (nút bấm), text field (ô gõ văn bản)… ViewGroup là các khung dùng để chứa các đối tượng View khác, ViewGroup quy định kích thước cũng như vị trí của các View con nằm trong nó, chẳng hạn như sắp xếp các View theo chiều dọc/ngang, hoặc theo dạng bảng…

Android định nghĩa một tập các thẻ XML tương ứng với các lớp ViewViewGroup để chúng ta có thể thiết kế giao diện theo cú pháp XML một cách dễ dàng.

Từ lớp gốc ViewGroup, các lớp con kế thừa được gọi với tên là Layout. Trong phần này chúng ta sẽ làm việc với LinearLayout.

Tạo LinearLayout

Chúng ta dùng thẻ LinearLayout trong file main.xml như sau:

<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:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
<LinearLayout>

Lớp LinearLayout kế thừa từ lớp ViewGroup, lớp này sẽ sắp xếp các View con theo chiều ngang hoặc chiều dọc. Các phần tử sẽ được sắp xếp theo thứ tự mà chúng được khai báo trong file XML này.

android:orientation="horizontal"

Thuộc tính android:orientation sẽ quy định là sắp xếp theo chiều ngang hay dọc, ở đây horizontal là ngang, còn vertical sẽ là dọc.

android:layout_width="match_parent"
android:layout_height="match_parent"

Hai thuộc tính android:layout_widthandroid:layout_height là bắt buộc phải có, 2 thuộc tính này sẽ quy định kích thước cho đối tượng View. Giá trị "match_parent" tức là kích thước của View con sẽ bằng kích thước của View cha, nhưng vì LinearLayout là lớp View gốc, tức là lớp này không có View cha nào cả nên ở đây lớp LinearLayout này sẽ có kích thước bằng với kích thước màn hình.

Thêm TextField

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="horizontal" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent">
    <EditText android:id="@+id/edit_message" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:hint="@string/edit_message" />
</LinearLayout>

Chúng ta thêm thẻ EditText vào bên trong thẻ LinearLayout.

android:id="@+id/edit_message"

Thuộc tính android:id là một cái tên riêng dành cho đối tượng View mà chúng ta đã khai báo, chúng ta có thể tham chiếu tới id này giống như tham chiếu tới biến trong các file .java. Dấu @ có nghĩa là giá trị của biến này được định nghĩa trong các đối tượng resource (tiếng Anh là tài nguyên) chứ không khai báo trực tiếp ở đây, theo sau dấu @ là loại resource, ở đây là id, tiếp theo là dấu / và tên resouce edit_message.

Dấu + phía trước id có nghĩa là tại đây chúng ta định nghĩa luôn id chứ mặc định Android không biết id là cái gì cả. Khi chúng ta dịch project thì SDK sẽ nhìn cái id đó và định nghĩa một lớp có tên là ID bên trong file gen/R.java, các resource có cùng loại id sau này sẽ tự động được thêm vào ở lớp ID này để gán vào các thẻ View của chúng ta. Khi chúng ta định nghĩa một loại resource mà có dấu + thì các resource sau này có cùng loại không cần phải có dấu + nữa.

android:layout_width="wrap_content"
android:layout_height="wrap_content"

Hai thuộc tính layout_widthlayout_height cũng giống với LinearLayout, nhưng ở đây chúng ta sử dụng giá trị wrap_content, giá trị này quy định kích thước của View là vừa đủ để bọc lấy nội dung bên trong nó, chẳng hạn như EditText có 3 kí tự thì kích thước sẽ tự động co dãn để vừa khớp với 3 kí tự đó.

android:hint="@string/edit_message"

Thuộc tính android:hint sẽ hiển thị một chuỗi mặc định nếu chúng ta không gõ gì vào text field. Ở đây giá trị của thuộc tính này tham chiếu tới biến edit_message trong loại resource là string, đây là loại resource có sẵn trong file strings.xml của project nên chúng ta không cần phải thêm dấu + vào làm gì, nhưng chúng ta phải khai báo biến edit_message trong file này, chúng ta sẽ khai báo ở dưới.

Mặc dù cả 2 thuộc tính android:idandroid:hint đều tham chiếu tới resource có cùng tên là edit_message nhưng đây là 2 resource khác nhau vì chúng nằm trong 2 loại resource khác nhau là idstring.

Khai báo tài nguyên string

Mặc định khi tạo project Android thì project này có một file resource chứa loại stringres/values/strings.xml.

<?xml version="1.0" encoding="utf-8"?>
<resources>
     <string name="app_name">MainActivity</string>
     <string name="edit_message">Enter a message</string>
     <string name="button_send">Send</string>
     <string name="action_settings">Settings</string>
</resources>

Chúng ta sẽ khai báo thêm một số resource ở đây.

<string name="edit_message">Enter a message</string>

Dòng code trên là cách khai báo một resource có kiểu là string với tên là edit_message, giá trị là Enter a message.

Thường thì khi thiết kế giao diện mà có những giá trị text thì chúng ta nên khai báo bằng biến trong file resource chứ không nên khai báo trực tiếp, tức là thay vì khai báo android:hint="Enter a message" thì chúng ta nên khai báo android:hint="@string/edit_message" hơn, rồi trong file strings.xml chúng ta khai báo thẻ string với nameedit_message. Điều này giúp chúng ta dễ dàng sửa đổi cũng như cập nhật lại sau này.

Thêm Button

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent">
    <EditText android:id="@+id/edit_message" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:hint="@string/edit_message" />
    <Button android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="@string/button_send"/>
</LinearLayout>

Chúng ta thêm một đối tượng ViewButton.

Các thuộc tính của thẻ Button cũng giống các thuộc tính của 2 thẻ kia, chỉ khác ở chỗ là ở đây chúng ta không khai báo id, thuộc tính id là một thuộc tính không bắt buộc.

Hiện tại giao diện của ứng dụng mà chúng ta đã thiết kế sẽ như hình bên dưới.

Capture

Nhìn thì có vẻ không có vấn đề gì, nhưng nếu chúng ta nhập một chuỗi có chiều dài lớn hơn kích thước màn hình thì text field sẽ tự dãn ra và đẩy button biến mất.

Để giải quyết vấn đề này chúng ta có thể dùng đến thuộc tính android:layout_weight, thuộc tính này quy định kích thước của các View theo tỉ lệ.

Ví dụ nếu chúng ta khai báo EditTextweight là 2 và Buttonweight là 1, như thế màn hình sẽ được chia làm 1 + 2 = 3 phần, trong đó EditText sẽ chiếm 2 phần và Button sẽ chiếm 1 phần. Khi chạy ứng dụng thì các View sẽ tự động dãn ra để lấp vừa 3 phần đó, nhưng dãn vừa đủ để EditText vẫn chiếm 2/3 kích thước còn Button chiếm 1/3 kích thước.

Chúng ta sửa lại main.xml như sau:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="horizontal" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent">
    <EditText android:id="@+id/edit_message" 
        android:layout_width="0dp" 
        android:layout_height="wrap_content" 
        android:layout_weight="1" 
        android:hint="@string/edit_message" />
    <Button android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="@string/button_send"/>
</LinearLayout>

Mặc định thuộc tính weight của các View là 0, nếu chúng ta khai báo weight cho View nào lớn hơn 0 thì view đó sẽ tự động dãn kích thước ra để lấp đầy khoảng trống còn thừa. Ở đây chúng ta khai báo weight cho EditText là 1.

android:layout_width="0dp"

Ngoài ra ở đây chúng ta cũng thiết lập lại thuộc tính android:layout_width của EditText là 0 bởi vì mặc định wrap_content sẽ yêu cầu ứng dụng phải tính toán kích thước của View dựa trên số lượng kí tự trong đó, nhưng sau đó thuộc tính weight lại yêu cầu ứng dụng dãn EditText ra để vừa khít với phần kích thước còn thừa, như thế việc tính toán kích thước của wrap_content là chẳng để làm gì cả, do đó chúng ta thiết lập “đại” sẵn một con số cụ thể nào đó luôn để ứng dụng khỏi mất công tính nữa, như thế sẽ tăng tốc độ thực thi của ứng dụng lên rất nhiều.

Capture

Chúng ta biên dịch và chạy lại ứng dụng với giao diện mới như hình trên.

0 0 votes
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments