Android Bài 9: Đi Sâu Vào Widget

Posted by

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

Chào mừng các bạn quay trở lại với bài học thứ 9 trong chương trình học Android của Yellow Code Books.

Chắc bạn còn nhớ ở bài 7, bạn đã làm quen với việc tạo một giao diện khá cơ bản cho TourNote, khi đó bạn đã biết về mối tương quan giữa ViewWidget. Bài học hôm nay sẽ giúp bạn hiểu rõ hơn, cũng như sẽ biết cách sử dụng tốt hơn vài widget cơ bản nhất trong lập trình Android. Sau bài học này thì mình cũng có viết một bài mở rộng, nơi đó mình nói về tất cả các widget còn lại mà bài học hôm nay chưa kịp nói đến.

Nào trước khi vào từng widget cụ thể, chúng ta hãy đi qua các khái niệm sau.

Khái Niệm Thuộc Tính (Attribute)

Các Thuộc Tính của một view được dùng để định nghĩa các biểu hiện của một view đó. Chẳng hạn như vị trí của chúng, độ rộng & chiều cao của chúng, màu sắc, nội dung,…

Đa số các thuộc tính đều được định nghĩa thông qua các câu lệnh XML mà ở bài 7 bạn có thực hành sơ qua. Một số ít trường hợp còn lại các thuộc tính sẽ được định nghĩa bằng Java code, nhằm phục vụ một số ý đồ thay đổi diện mạo cho view đó ở runtime.

Một ví dụ để bạn biết nơi tham khảo tất cả các thuộc tính của một view, bạn hãy vào link này, đây là ví dụ cho TextView. Khi đã mở link ra thì bạn hãy nhìn vào bảng “XML attributes”, bảng này sẽ liệt kê tất cả các thuộc tính bằng XML của TextView. Kéo xuống bảng ở dưới một tí là “Inherited XML attributes”, bảng này liệt kê tiếp tất cả các thuộc tính XML mà TextView đó kế thừa từ view gốc, nếu bạn chưa hiểu khái niệm kế thừa là gì thì bạn cứ nhớ rằng tất cả các thuộc tính XML của TextView này sẽ nằm ở cả 2 bảng vừa nhắc đến trên đây. Và ở dưới trang này còn một bảng hữu dụng nữa là “Public methods”, bảng này chứa các thuộc tính mà bạn có thể gọi đến ở Java code cho các mục đích thay đổi runtime được nhắc đến ở trên.

Một Số Thuộc Tính Quan Trọng Của View

View Nào Cũng Nên Có ID

Bạn thử nghĩ xem nếu bạn muốn tô màu cho một view, hay set text cho chúng, cách tốt nhất để có thể phân biệt xem view nào là view nào, là đặt cho chúng một ID rồi gọi chúng thông qua ID này. ID thực ra là một cái tên do bạn đặt cho các view hay widget. Tất nhiên cũng có view không cần bạn phải đặt một ID, vì chúng luôn luôn hiển thị với một trạng thái trong suốt quá trình sống của ứng dụng, chúng không bị thay đổi, và không ảnh hưởng đến vị trí hiển thị của view nào khác cả.

Định Nghĩa ID Cho Một View

Để định nghĩa một ID cho view (hay viewgroup), bạn có thể viết ngắn gọn như sau.

android:id="@+id/id_của_view"

Chúng ta sẽ đi qua từng phần trong cách định nghĩa trên.

android:id – Thuộc tính này được dùng khi bạn muốn định nghĩa một ID cho view hay viewgroup.

@+id/  – Báo cho hệ thống biết bạn muốn tạo mới một ID. Nhớ là phải có dấu “+”.

 id_của_view  – Là tên bạn tự đặt (theo chuẩn đặt tên biến của Java, nếu bạn nào có nhu cầu có thể xem cách đặt tên biến ở bài học Java này).

Truy Xuất Đến ID Của Một View

Bạn vừa mới tạo một ID, nếu bạn muốn gọi đến view thông qua ID này thì có các cách sau.

Nếu gọi đến ID trong file XML bạn có thể dùng cú pháp.

thuộc_tính_android="@id/id_của_view"

thuộc_tính_android – Một số thuộc tính của Android. Như bạn sẽ làm quen ở ngay dưới phần thực hành của bài học này, hay cụ thể hơn ở Bài 10, khi đó với layout có tên là RelativeLayout sẽ bắt bạn phải chỉ định vị trí tương quan giữa các view, và vì vậy bạn sẽ gọi đến ID của view khác thông qua thuộc tính android:layout_below như sau android:layout_below=”@id/id_của_view”.

@id/ – Khác với khi định nghĩa một ID mới, khi đó bạn phải dùng dấu “+” phía sau ký tự “@”. Lần này truy xuất đến ID đã định nghĩa, bạn chỉ cần gọi @id/ mà thôi.

id_của_view – Chính là ID mà bạn đã định nghĩa.

Nếu gọi đến ID trong Java code, bạn phải truyền R.id.id_của_view vào một số hàm, ví dụ hàm này findViewByID(R.id.id_của_view);

View Nào Cũng Cần Có Kích Cỡ

Kích cỡ ở đây là các định nghĩa về chiều ngang & dọc của view. Vậy chúng ta có 2 thuộc tính liên quan đến xác định kích cỡ cho view như sau (lưu ý là bạn có thể không cần định nghĩa ID cho view, nhưng bạn buộc phải định nghĩa kích cỡ, nếu không thì hệ thống sẽ báo lỗi).

android:layout_width
android:layout_height

Do trong lập trình mobile, bạn sẽ không biết chính xác ứng dụng của bạn sẽ được chạy trên kích thước màn hình nào, có hàng ngàn kích thước màn hình khác nhau trên thị trường, do đó để xác định được kích cỡ của một view sao cho hoàn hảo khi ứng dụng được chạy lên là điều tưởng chừng khó khăn. Nhưng với Android bạn có các cách khai báo kích cỡ sau.

1. Bạn có thể chỉ định giá trị match_parent, với giá trị này thì view của bạn sẽ thoải mái bung ngang hay bung dọc sao cho có thể dàn hết không gian mà view cha của view đó cho phép. Ví dụ một view được set thuộc tính android:layout_width=”match_parent” sẽ có chiều ngang hết cỡ trong khoảng chiều ngang của view cha, và nếu thuộc tính android:layout_height=”match_parent” thì sẽ có chiều cao hết cỡ trong khoảng chiều cao của view cha.

2. Bạn có thể chỉ định giá trị wrap_content, với chỉ định này thì view của bạn sẽ có kích thước co dãn sao cho đủ không gian cho các thành phần con bên trong nó.

3. Chỉ định kích cỡ cụ thể. Hai cách trên khá tốt, với màn hình khác nhau bạn cũng không sợ, vì bạn có thể chỉ định một view rộng hết màn hình, hay rộng trong khoảng thành phần con của nó thôi. Tuy nhiên còn 1 cách nữa là bạn có thể chỉ định độ lớn mong muốn theo một giá trị dp, ví dụ bạn set android:layout_width=”125dp” (hoặc 125dip cũng được, 2 ký hiệu viết tắt này đều là density independent, biểu thị một giá trị ảo dựa trên tỉ lệ điểm ảnh của màn hình, giá trị này sẽ được mình nói đến ở bài sau vì nó cũng khá dài dòng).

Xây Dựng Một Số Widget Cho Tour Note

Chúng ta chính thức làm quen với từng widget cụ thể.

TextView – Nơi Hiển Thị Các Label

Lại nhắc đến bài số 7, khi đó bạn đã tạo một TextView bên trong file activity_main.xml rồi, với TextView này bạn đã biết công dụng của nó là hiển thị thông báo đến người dùng khi không có ghi chú nào trong ứng dụng được tạo. Đúng vậy, TextView chính là một label, widget này chuyên dùng để hiển thị các đoạn text mang tính thông báo mà người dùng không thể chỉnh sửa được.

Các Thuộc Tính Thường Dùng Của TextView

Ngoài các thuộc tính quan trọng được nói ở trên sẽ thường được sử dụng, TextView còn có các thuộc tính thường dùng của riêng nó như sau.

android:gravity – Dùng để canh chỉnh text của nó sao cho canh trái, phải, giữa,… so với không gian của chính nó.

android:text – Bạn đã dùng đến thuộc tính này để set text cho TextView ở bài trước rồi đúng không nào.

android:textColor – Hiển thị màu cho text, bài thực hành hiển thị màu sẽ được mình nói đến ở bài viết đi sâu hơn về resource.

android:textSize – Kích cỡ của text, kích cỡ này được tính theo đơn vị sp. Định nghĩa và cách sử dụng đơn vị này sẽ được nói đến ở bài khác, cùng với các định nghĩa về dpdip được nhắc đến ở trên.

android:textAllCaps – Dùng để in hoa hết tất cả các ký tự của text nếu giá trị thuộc tính này là true.

android:padding – Set khoảng cách giữa biên của view đến các thành phần con của nó. Đơn vị tính của thuộc tính này cũng là dp hoặc dip. Nếu bạn muốn khoảng cách riêng cho từng cạnh biên có thể dùng tách biệt từng thuộc tính cụ thể của padding như android:paddingTop, android:paddingBottom, android:paddingLeftandroid:paddingRight.

android:ellipsize – Dùng thuộc tính này khi bạn muốn text của mình sẽ bị cắt và hiển thị “…” khi không đủ không gian để chứa hết text đó.

android:background – Thuộc tính này ở view cha, dùng để set màu nền hoặc ảnh nền cho view.

Thực Hành Hoàn Thiện Các Thuộc Tính Cho TextView

Bây giờ các bạn hãy mở lại project TourNote lên, chúng ta tiến hành chỉnh sửa lại TextView ở bài trước cho đúng đắn và chuyên nghiệp hơn.

Bạn mở lại file activity_main.xml ra, chúng ta thêm các thuộc tính sau vào trong TextView.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.yellowcode.tournote.MainActivity">
 
    <TextView
        android:id="@+id/activity_main_tv_empty"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="4dp"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:text="@string/empty_note"
        android:textSize="15sp"/>
 
</RelativeLayout>

Bạn vừa mới thêm vào các thuộc tính quan trọng cho TextView, các thuộc tính quan trọng này như đã nói ở trên, bao gồm.

– android:id – Bạn đặt ID cho TextView này là activity_main_tv_empty, sở dĩ mình đặt dài dòng như vậy là vì muốn đảm bảo ID này không bị trùng trong ứng dụng của chúng ta, để làm vậy thì chúng ta nên đặt có đủ 3 thành tố sau: tên_file_xml + viết_tắt_của_widget + tên_widget. Theo đó thì tên file xml là activity_main, viết tắt của TextView là tv, và tên của TextView này thông báo không có ghi chú nên đặt là empty. Cộng lại chúng ta có ID như trên.

android:layout_width – Được set là match_parent, tức là chiều rộng sẽ là maximum so với chiều rộng của view cha.

android:layout_height – Được set là wrap_content, tức chiều cao sẽ tùy theo số dòng của text.

android:padding – Được set là 4dp, bạn sẽ thấy một khoảng cách giữa text bên trong và đường biên của TextView hiện tại.

android:gravity – Được set là center, tức text sẽ nằm ở giữa so với biên của TextView này.

android:text – Nội dung mà TextView hiển thị.

android:textSize – Độ lớn của text hiển thị, hiện tại được set là 15sp.

Ảnh (Image) Sẽ Giúp Ứng Dụng Trông Pro Hơn

TextView không thôi vẫn chưa đủ mạnh (strong), người dùng sẽ bỏ qua câu thông báo của bạn ngay (ví dụ như trong trường hợp này của ứng dụng TourNote), bạn cần phải có một ảnh làm cho ứng dụng thêm đẹp hơn và người dùng chú ý nhiều hơn tới câu thông báo. Ngoài ra trong ứng dụng sẽ cần dùng đến rất nhiều ảnh, do đó mình xin nói đến cách sử dụng ảnh rất sớm từ bài này.

Có 2 widget giúp hiển thị ảnh trong Android, đó là ImageViewImageButton. Bài hôm nay chỉ nói về ImageView thôi, trong khi ImageButton là con của ImageView nên cũng có các thuộc tính tương tự ImageView. Tất cả các widget đã được mình tổng hợp lại trong bài Tìm Hiểu Các Widget Cơ Bản, các bạn vào xem nhé.

Các Thuộc Tính Thường Dùng Của ImageView

Tương tự như TextView sẽ kế thừa các thuộc tính quan trọng từ view cha, ImageView cũng có các thuộc tính kế thừa đó và các thuộc tính quan trọng của riêng nó như sau.

android:src – Hiển thị ảnh theo dạng content, ảnh này sẽ nằm đè lên trên ảnh background nói đến ở dưới đây.

android:background – Thuộc tính này ở view cha, dùng để set màu nền hoặc ảnh nền cho view.

android:scaleTyle – Cho biết tỉ lệ co dãn hoặc vị trí của ảnh so với khung của view, các giá trị của thuộc tính này sẽ được nói kỹ sau bài thực hành dưới đây.

android:padding – Tương tự padding của TextView ở trên. Tuy nhiên padding sẽ làm ảnh hưởng đến không gian hiển thị của src, với background thì “miễn nhiễm” với thuộc tính này.

Thực Hành Thêm ImageView Cho TourNote

Trước hết bạn hãy nhấn vào đây để download resource.

Resource bạn vừa down về chứa đựng nhiều thư mục (drawable-mdpi/drawable-hdpi/drawable-xhdpi/drawable-xxhdpi/ và drawable-xxxhdpi/), bạn giải nén và copy các thư mục này vào thư mục res/ của project TourNote, trong các thư mục đều chứa một ảnh có tên giống nhau là empty_note.png. Bạn biết tại sao ảnh này lại để trong các thư mục này đúng không nào, đó là cách bạn xác định ảnh cho alternative resource (bạn có thể xem bài 8 nếu chưa biết về alternative resource), để khi load lên, độ phân giải của ảnh sẽ được hiển thị chính xác nhất theo tỉ lệ mình hàn hình trên thị trường.

Bạn phải đảm bảo rằng sau khi giải nén và copy các thư mục chứa ảnh vào trong thư mục res/ của project, thì chúng phải hiển thị như hình sau trong ứng dụng, nếu không bạn có thể xóa các thư mục vừa tạo để copy lại, hoặc download source code mẫu theo đường link cuối bài học để check xem thế nào nhé.

Screen Shot 2016-10-17 at 13.39.27.png

Sau khi đã copy các ảnh như trên rồi chúng ta tiến hành code thêm cho activity_main.xml như sau.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.yellowcode.tournote.MainActivity">
 
    <TextView
        android:id="@+id/activity_main_tv_empty"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="4dp"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:text="@string/empty_note"
        android:textSize="15sp"/>
 
    <ImageView
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_below="@id/activity_main_tv_empty"
        android:layout_marginTop="8dp"
        android:layout_centerHorizontal="true"
        android:scaleType="fitCenter"
        android:src="@drawable/empty_note"/>
 
</RelativeLayout>

Giải nghĩa một số thuộc tính bạn thêm vào cho ImageView.

android:layout_width android:layout_height – Lần này bạn set một giá trị cụ thể cho kích cỡ của ảnh là là 60dp x 60dp.

android:layout_below – Thuộc tính này không thuộc ImageView, nó thuộc RelativeLayout mà chúng ta sẽ nói đến ở bài sau, nhưng bạn cũng nên chú ý, thuộc tính này có truyền vào một ID theo dạng @id/, như đã nói ở mục Truy xuất đến ID ở trên, tham số của ID này là activity_main_tv_empty chính là ID của TextView đã được khai báo, bạn gõ sai ID là hệ thống sẽ báo lỗi. Ý nghĩa của thuộc tính này là muốn ImageView được thêm vào mới này sẽ nằm dưới TextView, bạn thử bỏ thuộc tính này để xem nó lỗi như thế nào trên layout của ứng dụng nhé.

android:scaleType – Được set là fitCenter, chúng ta sẽ tìm hiểu các kiểu co dãn ảnh ở mục sau đây.

android:src – Được set là đường dẫn đến ảnh empty_note.png. Cách sử dụng chi tiết resource dạng image này sẽ được mình nói cụ thể sau.

Giờ bạn hãy thử run project lên để xem thành quả nhé.

device-2016-11-15-141631

Các Dạng Scale Của Ảnh

Bước thực hành trên đây chúng ta vừa làm quen với một dạng scale, đó là android:scaletype=”fitCenter”, các dạng scale này chính là do widget ImageView này hỗ trợ, nó giúp bạn có được các tùy chỉnh thú vị hơn khi sử dụng đến ảnh.

Chúng ta cùng xem qua các dạng scale có thể có của một ImageView nhé.

Giả sử mình dùng ảnh có hình con robot như sau ( bạn chú ý khung màu xanh dương là khung giới hạn của ImageView để xem chúng “biến hóa” như thế nào trong khung giới hạn).

fitCenter

Nếu sử dụng giá trị này cho scaleType, ảnh sẽ tự động scale sao cho hiển thị gọn bên trong khung mà tỉ lệ của ảnh vẫn không thay đổi.

Screen Shot 2016-10-17 at 14.44.55.png

fitXY

Giá trị này làm ảnh bị scale sao cho hiển thị gọn bên trong khung, nhưng khác fitCenter ở chỗ fitXY làm cho ảnh bị biến dạng không còn tỉ lệ gốc nữa.

Screen Shot 2016-10-17 at 15.03.40.png

fitStart

Cách scale này giống với fitCenter là sẽ đảm bảo ảnh nằm gọn trong khung mà tỉ lệ ảnh không đổi, nhưng thay vì ảnh nằm giữa khung thì nó bị neo góc trên bên trái khung.

Screen Shot 2016-10-17 at 15.15.33.png

fitEnd

Tương tự như fitStart, nhưng góc neo của ảnh lại là góc dưới bên phải khung.

Screen Shot 2016-10-17 at 15.38.55.png

centerCrop

Giá trị này làm ảnh sẽ bị scale đến khi một chiều ngắn nhất của ảnh nằm gọn trong khung, chiều còn lại bị cắt sao cho tỉ lệ của ảnh không bị đổi. Trường hợp dưới đây cho thấy chiều dọc của ảnh sẽ nhìn thấy gọn trong khung, trong khi chiều dài bị cắt.

Screen Shot 2016-10-17 at 14.52.48.png

center

Giá trị này không làm scale ảnh, nó chỉ có nhiệm vụ hiển thị ảnh đúng với kích cỡ của nó vào giữa khung mà thôi.

Screen Shot 2016-10-17 at 15.08.10.png

Nói như vậy có nghĩa là nếu như khung nhỏ hơn kích thước ảnh, ảnh sẽ bị cắt đi như hình sau.

Screen Shot 2016-10-17 at 15.21.57.png

centerInside

Cách scale này cũng giống như center, tức là nó cũng sẽ giữ kích thước gốc của ảnh, nhưng nếu khung vẫn còn nhỏ hơn kích thước ảnh, lúc này ảnh sẽ tự scale xuống mà vẫn giữ tỉ lệ của nó.

Group 3.png

matrix

Dùng khi bạn muốn scale ảnh và xoay ảnh dạng Matrix, bạn có thể search thêm cách scale hay xoay ảnh dạng Matrix trên mạng, hoặc mình sẽ viết cách sử dụng Matrix ở một bài khác.

Bạn vừa cùng mình thực hành 2 cách sử dụng widget là TextViewImageView, hãy đọc Tìm Hiểu Các Widget Cơ Bản để biết cách sử dụng các widget cơ bản còn lại bạn nhé.

Download Source Code Mẫu

Bạn có thể download source code mẫu của bài này ở đây.

Cảm ơn bạn đã đọc các bài viết của Yellow Code Books. Bạn hãy đánh giá 5 sao nếu thấy thích bài viết, hãy comment bên dưới nếu có thắc mắc, hãy để lại địa chỉ email của bạn để nhận được thông báo mới nhất khi có bài viết mới, và nhớ chia sẻ các bài viết của Yellow Code Books đến nhiều người khác nữa nhé.

Bài Kế Tiếp

Bạn sẽ được học rõ hơn cách sử dụng 2 layout phổ biến nhất hiện nay là LinearLayout và RelativeLayout, qua đó bạn sẽ nắm rõ cách sắp xếp các View hay ViewGroup theo một trật tự nhất định để tạo thành một giao diện hoàn chỉnh của ứng dụng.

Advertisements
Rating: 4.9/5. From 10 votes.
Please wait...

6 comments

    1. Cảm ơn bạn Nam đã theo dõi các bài học của mình. Mình nghĩ không có vấn đề gì đâu bạn, bạn hoàn toàn có thể theo dõi và học song song cả Java và Android. Nhưng thời gian qua có nhiều bạn muốn biết vững Java hơn nên có lẽ mình đẩy nhanh Java một chút.
      Ngoài ra thì nếu có thắc mắc nào ở mỗi bài học, bạn Nam cứ comment nhé, mình sẽ chỉnh sửa lại nội dung các bài học sao cho dễ hiểu nhất có thể.

      1. Cám ơn anh, anh trình bày bài học vậy là chi tiết và dễ hiểu lắm rồi! Mong anh đẩy nhanh tiến độ bài viết hơn thôi! Chúc anh thêm nhiều sức khỏe để viết bài nhé!

Gửi phản hồi