Android Bài 13: Sử Dụng Style

Posted by

Được chỉnh sửa ngày 23/04/2019.

Chào mừng các bạn đã đến với bài học Android thứ 13, bài học về cách sử dụng Style. Đây là bài học trong chuỗi bài viết về lập trình ứng dụng Android bằng Java của Yellow Code Books.

Như đã hứa ở cuối bài trước, là từ bài học hôm nay chúng ta sẽ lần lượt nói về từng resource chuyên sâu của Android. Mình sẽ ưu ái nói đến resource Style trước, bởi vì nó là một resource đặc biệt, nó quyết định đến SỰ NHẤT QUÁN trong giao diện của ứng dụng của bạn.

Mình đã từng góp ý cho nhiều project của các bạn mới tham gia vào lập trình ứng dụng, đa số các bạn đều mắc một lỗi, đó là sự nhất quán. Bạn thử nghĩ xem ở màn hình thứ nhất, các Button của các bạn thiết kế với phong cách vuông, background màu xám, nhưng qua màn hình thứ hai thì phong cách bị đảo lộn với kiểu Button được bo tròn, background màu xanh. Chưa kể đến font size và chiều cao của các Button này không đồng nhất nữa. Đó là một ví dụ nhỏ về Button, các widget khác trong các ứng dụng này đều chịu một “số phận” tương tự, đó là việc thiếu nhất quán trong phong cách. Việc thiếu nhất quán này làm cho người dùng cảm thấy bối rối khi ở mỗi màn hình mỗi khác, họ sẽ đánh giá rằng ứng dụng của bạn thiếu sự đầu tư, thiếu chuyên nghiệp.

Vậy làm cách nào để cải thiện? Mời các bạn cùng xem qua bài học về Style nhé.

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 khai báo font cho Theme, rồi áp dụng Theme đó cho toàn bộ ứng dụng, 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 đó áp dụng 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.

Style - Nơi chứa file Style

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é.

Style - Cấu trúc file Style

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">match_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ách đặt tên cho Style cũng như cách đặt tên cho resource dạng String mà bạn đã thực hành ở Bài 8.

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 chúng.

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.

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

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

</resources>

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ề ConstraintLayout hay LinearLayout hay RelativeLayout trong tương lai.

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é.

Nếu bạn đang ở tab Design của cửa sổ này, thì hãy đảm bảo TextView ở giữa màn hình đang được chọn. Sau đó hãy tìm trong hộp thoại Attributes bên phải màn hình thuộc tính style. Có thể bạn phải nhấn vào View all attributes mới có thể tìm thấy field này.

Style - Thêm Style cho TextView bằng Design

Khi thấy field style, hãy đưa trỏ chuột vào field này bạn sẽ thấy bên phải có dấu ba chấm (). Nhấn vào đó sẽ dẫn bạn đến một dialog chọn Style đã được định nghĩa sẵn. Và vì có quá nhiều Style trong đây nên bạn hãy tìm bằng cách gõ từ khóa vào field tìm kiếm như sau.

Style - Tìm Style trong cửa sổ quản lý

Sau khi tìm thấy Style InformationTextView rồi thì bạn hãy nhấn chọn OK. Kết quả nhận được ở màn hình trực quan sau đó chẳng có gì khác lạ cả. Một phần vì Style mà bạn định nghĩa nó dựa trên các thuộc tính có sẵn của TextView này rồi, nên việc áp dụng nó vào đây cũng chẳng giúp gì. Nó sẽ hữu dụng khi bạn xây dựng TextView nào đó ở những chỗ khác, mà áp dụng Style InformationTextView này, thì sẽ giúp tiết kiệm khá nhiều công sức định nghĩa lại các thuộc tính giống với TextView này.

Tuy nhiên sự khác lạ sẽ ở code XML, bạn hãy chuyển qua tab Text ở cửa sổ thiết kế cho giao diện activity_main.xml này. Bạn sẽ thấy TextView hôm trước nay đã có thêm thuộc tính style.

<TextView
    android:id="@+id/activity_main_tv_empty"
    style="@style/InformationTextView"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginLeft="8dp"
    android:layout_marginTop="8dp"
    android:layout_marginRight="8dp"
    android:layout_marginBottom="8dp"
    android:gravity="center"
    android:text="@string/empty_note"
    android:textSize="15sp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

Bạn thấy rằng, mặc dù chúng ta không cần chỉnh sửa gì cả, vì giao diện của việc thêm style vào cho TextView có khác gì với không thêm đâu. Nhưng chúng ta cũng phải thực hành tiếp bước sau đây. Vì chắc bạn đã hiểu, Style giúp định nghĩa ra các thuộc tính chung nhất cho các view trong Android, nên khi áp dụng Style vào view rồi, chúng ta cũng nên bỏ đi khác khai báo trùng lắp giữa Style và view được áp dụng Style đó.

Vì vậy hãy quay trở lại activity_main.xml. Bạn vẫn để chế độ thiết kế ở tab Text để chỉnh sửa cho dễ. Chúng ta sẽ bỏ đi các thuộc tính dư thừa, và TextView lúc bấy giờ chỉ còn như sau.

<TextView
    android:id="@+id/activity_main_tv_empty"
    style="@style/InformationTextView"
    android:text="@string/empty_note"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
 

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"?>
<android.support.constraint.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/activity_main_tv_empty"
        style="@style/InformationTextView"
        android:text="@string/empty_note"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:scaleType="fitCenter"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/activity_main_tv_empty"
        app:srcCompat="@drawable/empty_note" />

</android.support.constraint.ConstraintLayout>

Download Source Code Mẫu

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

Chúng ta vừa đi sâu vào một dạng resource của Android, resource Style. Hi vọng các bạn sẽ thích thú với loại resource này.

Còn nhớ ngày xưa mình làm quen với Style khá muộn, khi mà hì hụi copy/paste các khai báo XML chán chường thì mình đọc đến Style, và bạn biết không khi đó mình nghĩ đây thực sự là một cây đũa phép trong lập trình. Nghĩ đến vẫn thấy đôi khi mình gà thật 🙂

Cảm ơn bạn đã đọc các bài viết của Yellow Code Books. Bạn hãy ủng hộ blog bằng cách:

Đánh giá 5 sao bên dưới mỗi bài nếu thấy thích.
Comment bên dưới mỗi bài nếu có thắc mắc.
Để lại địa chỉ email của bạn ở thanh bên phải để nhận được thông báo sớm nhất khi có bài viết mới.
Chia sẻ các bài viết của Yellow Code Books đến nhiều người khác.

Bài Kế Tiếp

Như đã hứa, bài tiếp theo chúng ta cùng nói đến Theme. Về cơ bản thì Theme vẫn giống như Style về cách khai báo, nhưng về ứng dụng thì có phần hơi khác một chút, các bạn chờ xem nhé.

Advertisements
Rating: 5.0/5. From 19 votes.
Please wait...

6 comments

Leave a Reply