Tìm Hiểu Và Sử Dụng Style Trong Android

Khái Niệm Style

Style – Phong cách. Như mình có trình bày ở trên, Phong Cách ở đây là muốn nói về cách mà bạn tạo ra một sự đồng nhất về giao diện cho ứng dụng. Như ví dụ về button trên đây, bạn muốn tạo ra các button giống nhau ở các màn hình, để cho nó có sự đồng nhất. Khi đó việc thiết kế cho button sao cho chúng giống nhau như vậy khiến bạn cảm thấy nhàm chán vì mất khá nhiều thời gian. Lúc đó bạn sẽ cần đến một nơi định nghĩa hết tất tần tật những thuộc tính của button trên, rồi đến với từng button bạn chỉ việc mang định nghĩa đó ra dùng. Thì khi đó Style chính là kiểu resource mà bạn đang tìm.

Nói Đến Style Phải Nói Đến Theme

Đã nói về Style thì mình cũng muốn các bạn làm quen với khái niệm Theme luôn. Vì về cơ bản, trong Android Theme không khác gì Style. Chúng đều giúp tạo ra sự đồng nhất về giao diện. Nhưng thay vì Style giúp áp dụng sự đồng nhất cho các view sử dụng nó, thì Theme lại giúp áp dụng sự đồng nhất cho toàn bộ Activity (toàn bộ màn hình) hoặc toàn bộ ứng dụng. Ví dụ như bạn áp dụng font cho Theme của một màn hình, thì tất cả các view trong màn hình đó đều được thay đổi font.

Nếu đến đây bạn vẫn còn mơi hồ về hai khái niệm Style và Theme, thì bạn cứ tưởng tượng chúng giống như khái niệm CSS (Cascading Style Sheets) trong lập trình Web vậy. CSS cũng giúp định hình các phong cách, để tạo nên sự đồng nhất cho các thẻ HTML bên trong trang Web đó.

Có một điều bạn cần phải nhớ là mặc dù Theme là một khái niệm để mang ra nói chung với Style, nhưng bạn không cần phải định nghĩa ra bất kỳ Theme nào cả. Bạn chỉ cần chọn một trong các Theme được xây dựng sẵn bởi hệ thống. Và vì kiến thức về Theme cũng kha khá nhiều và quan trọng, nên mình sẽ nói tiếp ở bài sau nhé, bài này sẽ tập trung cho Style.

Ví Dụ Về Sử Dụng Style

Nào, chưa cần nói gì về cách sử dụng Style nhé. Phần này đưa ra một ví dụ mà không nói quá chi tiết, để bạn có một cách hiểu tổng quát về Style trước, rồi chúng ta mới đi từ từ vào các cách thức cụ thể.

Giả sử mình có một TextView như sau.

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColor="#00FF00"
    android:typeface="monospace"
    android:text="@string/hello" />

Mình muốn TextView này là một TextView chuẩn, để ở các màn hình khác mình cũng sẽ định nghĩa các TextView giống vậy. Và thay vì mình phải khai báo lại các thuộc tính như trên cho tất cả các TextView ở các màn hình khác, thì mình chỉ cần tạo ra một Style có tên là CodeFont, rồi sau đó sử dụng đến Style này cho TextView này và các TextView về sau như sau.

<TextView
    style="@style/CodeFont"
    android:text="@string/hello" />

Vậy đó. Cách để áp dụng Style cho TextView đơn giản vậy thôi. Cách thức khởi tạo chi tiết hơn một Style được mô tả tiếp ở bước kế tiếp.

Chi Tiết Sử Dụng Style

Như mình có nói thì Style là một dạng resource của Android, vậy chắc chắn file Style phải ở đâu đó trong thư mục res/ rồi, và chính xác của thư mục chứa file Style này là res/values/. Bạn hãy mở thư mục này theo đường dẫn như hình bên dưới. Khi bạn tạo mới một project thì hệ thống cũng tạo sẵn cho chúng ta một file Style và để ở thư mục này, tên của file Style này là styles.xml.

screen-shot-2017-01-13-at-12-20-02

Và dĩ nhiên vì là một loại resource của Android, nên file Style cũng theo quy luật Alternative Resource và Default Resource. File styles.xml các bạn đang thấy trên hình thuộc về Default Resource, nhưng có thể project ở máy của bạn có chứa đựng một file styles.xml khác ở thư mục values-xxx/ nào khác thì có nghĩa file Style đó thuộc về Alternative Resource.

Cấu Trúc File styles.xml

Giờ thì chúng ta cùng mở file styles.xml ở thư mục Default Resource này lên nhé.

screen-shot-2017-01-13-at-12-33-48

Bạn có thể thấy rằng file styles.xml cũng giống như file strings.xml mà bạn đã làm quen hay tất cả các file .xml khác trong thư mục values/ mà bạn sẽ làm quen sau này cũng đều được để trong một thẻ gốc có tên resources.

Hình trên đây đang có một Style, mỗi Style mà bạn tạo ra sẽ được nằm trong cặp đóng mở thẻ có tên style. Và thẻ style duy nhất bạn thấy trong hình lại dùng như một Theme của ứng dụng, mà chúng ta sẽ nói về Theme này ở bài sau.

Còn bây giờ giả sử chúng ta cần tạo một Style có tên là CodeFont để dùng cho ví dụ về TextView ở trên, vậy mình sẽ thêm các dòng sau vào file styles.xml.

<style name="CodeFont" parent="@android:style/TextAppearance.Medium">
    <item name="android:layout_width">fill_parent</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:textColor">#00FF00</item>
    <item name="android:typeface">monospace</item>
</style>

Khi đó ở mọi nơi mà mình muốn dùng đến Style này, mình sẽ gọi đến bằng thuộc tính style như sau.

<TextView
    style="@style/CodeFont"
    android:text="@string/hello" />

Giờ thì chúng ta hãy làm quen với những gì có thể có bên trong thẻ style nhé, rồi sau đó cùng nhau thực hành tạo style cho TourNote ở bên dưới bài học này.

Thuộc Tính name

Đây là tên của Style, như bạn thấy ở ví dụ trên tên này là CodeFont, bạn phải đặt tên cho bất kỳ Style nào mà bạn đặt ra để có thể dùng đến sau này.

Các Thẻ item

Chà, như Style ví dụ trên đây thì sau thuộc tính name còn có thuộc tính parent. Nhưng mình xin phép được nói đến các thẻ item trước vì nó quan trọng hơn.

Mỗi thẻ item như vậy định nghĩa ra một loại phong cách nào đó, trong đó tên của loại phong cách đó được miêu tả trong thuộc tính name của thẻ này, như bạn đã thấy trong ví dụ, các tên này như là “android:layout_width”, “android:layout_height”, “android:textColor”“android:typeface” và còn nhiều tên nữa… Bạn có thể thấy các giá trị cho thuộc tính name này đều là các thuộc tính của các widget hay của layout chứa widget đó mà bạn đã làm quen trong việc thiết kế giao diện trước đây. Như vậy Style cũng chính là nơi bạn lấy các thuộc tính có sẵn ra, rồi định nghĩa cho chúng một giá trị nào đó, rồi áp dụng lại cho các widget, đó chính là khái niệm Phong Cách trong bài học hôm nay.

Theo sau các khai báo name trong thẻ này là các giá trị của nó, đó có thể là một kiểu String, một giá trị màu sắc, hay một độ lớn dp, sp,… tùy thuộc vào từng loại phong cách.

Thuộc Tính parent

Thuộc tính này không bắt buộc. Nhưng nếu bạn muốn Style của mình được kế thừa từ một Style có sẵn (do bạn tạo ra trước đó, hay từ Style của một thư viện nào đó, hoặc Style của hệ thống), việc kế thừa này giúp bạn tận dụng lại những định nghĩa từ Style gốc, và tạo ra các định nghĩa mới bổ sung cho Style gốc còn thiếu.

Như ví dụ từ định nghĩa trên đây, bạn sẽ thấy Style dành cho TextView có kế thừa từ một Style của TextView có sẵn của hệ thống, đó là “@android:style/TextAppearance.Medium”. Ngoài việc dùng lại tất cả những thuộc tính được khai báo sẵn của hệ thống, thì Style CodeFont trên lại định nghĩa mới các thuộc tính về layout_width, layout_height, textColor, và typeface cho riêng mình.

Còn nếu bạn muốn biết nhiều hơn về ví dụ cách kế thừa từ một Style do bạn tạo ra, thì mời bạn xem đoạn định nghĩa các Style bên dưới.

<style name="BaseTextViewStyle">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:textColor">@color/cl_default</item>
    <item name="android:textSize">@dimen/text_size_normal</item>
</style>
 
<style name="LargeTextViewStyle" parent="BaseTextStyle">
    <item name="android:textSize">@dimen/text_size_large</item>
</style>
 
<style name="SmallTextViewStyle" parent="BaseTextStyle">
    <item name="android:textSize">@dimen/text_size_small</item>
</style>

Với ví dụ này thì mình định nghĩa ra một Style chung cho nhiều TextView có tên là BaseTextViewStyle. Sau đó mình có thêm hai Style nữa là LargeTextViewStyleSmallTextViewStyle đều có thuộc tính parent chỉ đến BaseTextViewStyle, nhưng hai Style con lại có cách định nghĩa riêng giá trị textSize cho mình.

Lưu ý là với việc kế thừa từ Style của bạn ở cùng một file, thì bạn có thể không cần đến khai báo parent nữa mà dùng dấu chấm như thế này cũng được.

<style name="BaseTextStyle.LargeTextViewStyle">
    <item name="android:textSize">@dimen/text_size_large</item>
</style>
 
<style name="BaseTextStyle.SmallTextViewStyle">
    <item name="android:textSize">@dimen/text_size_small</item>
</style>

Thực Hành Tạo Style Cho TourNote

Chà lý thuyết nhiều quá, hi vọng các bạn đã nắm tốt kiến thức về Style.

Quay trở lại với bài thực hành, ở các bài thực hành trước, chúng ta đã tạo ra một TextView ở giữa màn hình để hiển thị thông báo cho người dùng biết rằng chưa có ghi chú nào được tạo và người dùng phải tạo ra ghi chú mới. Nhưng bạn cũng nên biết trong ứng dụng cũng sẽ có nhiều các câu thông báo như vậy. Vậy thì để tiết kiệm thời gian sau này mỗi khi bạn cần hiển thị một thông báo ở đâu đó, thay vì thiết kế lại các thuộc tính cho các câu thông báo, thì chúng ta sẽ tạo một Style đầu tiên dành cho các câu thông báo như thế này ở mọi nơi trong ứng dụng TourNote của chúng ta.

Tạo Style

Để bắt đầu, bạn hãy mở file styles.xml của TourNote lên nhé. Bạn chớ có xóa đi Style hiện có trong file này, mà hãy thêm một Style mới bên dưới Syle đã có như sau.

<style name="InformationTextView">
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:padding">4dp</item>
    <item name="android:gravity">center</item>
    <item name="android:textSize">15sp</item>
</style>

Bạn thấy rằng Style được tạo ra này có tên là InformationTextView. Trong đó có các thuộc tính được định nghĩa là phong cách cho loại TextView này, bao gồm layout_widthlayout_height, padding, gravitytextSize.

Tại sao những thuộc tính khác của TextView này không được sử dụng làm Style? Bởi vì hoặc là chúng không mang tính đặc trưng sẽ được dùng đi dùng lại nhiều lần, như thuộc tính text chẳng hạn. Hay chúng là các thuộc tính của layout cha, mà nếu như vậy thì ai mà biết được TextView sẽ thuộc về LinearLayout hay RelativeLayout trong tương lai, nên thuộc tính layout_centerInParent (thuộc về RelativeLayout) cũng sẽ không được sử dụng để làm Style.

Sử Dụng Style

Với việc tạo ra một Style như trên đây, thì bước này chúng ta áp dụng Style đó vào TextView cần thiết. Bạn hãy mở file activity_main.xml lên nhé. Với TextView trong file xml này, bạn hãy thêm vào Style chúng ta cần áp dụng cho TextView, code của TextView khi này trông như sau.

<TextView
    android:id="@+id/activity_main_tv_empty"
    style="@style/InformationTextView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:gravity="center"
    android:padding="4dp"
    android:text="@string/empty_note"
    android:textSize="15sp" />

Style được gọi đến với thuộc tính style, và tên của Style bạn muốn dùng đến sẽ nằm sau ký hiệu “@style/” bên trong thuộc tính này. Cách gọi đến Style trong XML như thế này cũng tương tự như khi bạn gọi đến ID bằng “@id/”, hay dùng đến String bằng cách “@string/”, hay dùng đến ảnh trong resource Drawable bằng cách “@drawable/” ở các bài thực hành trước vậy.

Và bởi vì Style đã giúp định nghĩa vài thuộc tính dùng chung rồi, do đó bạn có thể không cần định nghĩa lại các thuộc tính đó trong TextView. Bạn tiếp tục chỉnh sửa TextView thành ra như sau.

<TextView
    android:id="@+id/activity_main_tv_empty"
    style="@style/InformationTextView"
    android:layout_centerInParent="true"
    android:text="@string/empty_note" />

Bạn có thể thấy rằng với Style thì việc định nghĩa ra các widget tương tự nhau là dễ dàng, chẳng những vậy chúng còn giúp rút ngắn khai báo các widget của bạn nữa. Thật là tiện lợi.

Và đây là tổng thể code của màn hình activity_main.xml cho đến lúc này.

<?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"
        style="@style/InformationTextView"
        android:layout_centerInParent="true"
        android:text="@string/empty_note" />
 
    <ImageView
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_below="@id/activity_main_tv_empty"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="8dp"
        android:scaleType="fitCenter"
        android:src="@drawable/empty_note" />
 
</RelativeLayout>

AndroidCoBan via yellowcodebook

Nguyễn Linh

Chia sẻ để cùng tiến bộ...

Bình luận đã bị khoá.