+2

Custom Attributes in Android

Tạo các thuộc tính tuỳ chỉnh trong Android để custom View sử dụng XML

Một giao diện tùy chỉnh được thiết kế tốt giống như bất kỳ các lớp được thiết kế sẵn khác. Nó đóng gói một tập hợp các chức năng với một giao diện dễ sử dụng, nó sử dụng CPU và bộ nhớ hiệu quả ... Ngoài việc lớp tuỳ chỉnh được thiết kế tốt, một giao diện tùy chỉnh nên:

  • Phù hợp với tiêu chuẩn Android

  • Cung cấp các thuộc tính tuỳ chỉnh (Styleable Attributes) để làm việc với layout sử dụng XML

  • Gửi các sự kiện để truy cập

  • Tương thích với nhiều nền tảng Android

Android Framework cung cấp một tập hợp các lớp cơ sở (base classes) và các thẻ (tag) XML để giúp bạn tạo 1 View đáp ứng được tất cả các yêu cầu trên.

Lớp con của View

Tất cả các lớp View trong Android Framework đều kế thừa từ View. Để tạo 1 view tuỳ chỉnh bạn cũng kế thừa trực tiếp từ View, hoặc bạn có thể tiết kiệm thời gian bằng cách kế thừa một trong những subclass của View, chẳng hạn như lớp Button.

Để cho phép Các Công Cụ Phát Triển Android (Android Developer Tools) tương tác với View của bạn, ít nhất bạn phải cung cấp một hàm khởi tạo (constructor) và truyền tham số vào nó một đối tượng Context và một AttributeSet. Hàm khởi tạo này cho phép trình biên tập Layout (layout editor) tạo và chỉnh sửa lớp View của bạn.

class PieChart extends View {
    public PieChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

Xác định tuỳ chỉnh các thuộc tính (Custom Attributes)

Để thêm vào các thuộc tính dựng sẵn cho View, bạn xác định cho nó một thành phần XML và kiểm soát sự xuất hiện và hành vi của nó với các thành phần thuộc tính. Để cho phép hành vi này trong giao diện tuỳ chỉnh, bạn phải:

  • Định nghĩa các thuộc tính tuỳ chỉnh cho View của bạn trong thành phần <declare-styleable>

  • Xác định các giá trị cho các thuộc tính trong layout XML.

  • Nhận về các giá trị của thuộc tính tại thời điểm chạy (runtime)

  • Áp dụng các giá trị thuộc tính nhận được tới View của bạn

Phần này thảo luận về cách làm thế nào định nghĩa các thuộc tính tuỳ chỉnh và xác định các giá trị cho chúng. Phần tiếp theo là việc lấy về và áp dụng các giá trị của các thuộc tính tại thời điểm chạy.

Để định nghĩ các thuộc tính tuỳ chỉnh, thêm tài nguyên (resource) <declare-styleable> tới dự án của bạn. Đây là các quy định để định kiểu các thuộc tính bên trong tệp tin res/values/attrs.xml. Đây là một ví dụ của một tệp tin attrs.xml :

<resources>
   <declare-styleable name="PieChart">
       <attr name="showText" format="boolean" />
       <attr name="labelPosition" format="enum">
           <enum name="left" value="0"/>
           <enum name="right" value="1"/>
       </attr>
   </declare-styleable>
</resources>

Đoạn mã này khai báo 2 thuộc tính tuỳ chỉnh, showTextlablePosition, chúng thuộc về một styleable có tên PieChart. Tên của thực thể stylable là theo quy ước (convention), tên giống như tên của lớp định nghĩa các giao diện tuỳ chỉnh.

Một khi bạn xác đinh được các thuộc tính tuỳ chỉnh, bạn có thể sử dụng chúng in các bố trí XML như các thuộc tính được dựng sẵn. Sự khác biệt duy nhất là các thuộc tính tuỳ chỉnh của bạn phải khai báo một namespace khác nhau.

Thay vì thuộc về namespace http://schemas.android.com/apk/res/android thay vào đó bạn sử dụng http://schemas.android.com/apk/res/[your package name] . Cho ví dụ, đây là cách bạn sử dụng các thuộc tính được tuỳ chỉnh trong tệp tin bố trí XML PieChart:

<? xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:custom="http://schemas.android.com/apk/res/com.example.customviews">
 <com.example.customviews.charting.PieChart
     custom:showText="true"
     custom:labelPosition="left" />
</LinearLayout>

Để tránh việc lặp lại các URI namespace, sử dụng định nghĩa xmlns. Chỉ thị này được gán một bí danh (alias) custom tới namespace http://schemas.android.com/apk/res/com.example.customviews . Bạn có thể chọn bất kì alias nào bạn muốn cho namespace của bạn.

Chú ý tên của thẻ XML cho biết các thuộc tính được tuỳ chỉnh được thêm vào bố trí của bạn. Nó là tên đầy đủ các lớp giao diện tuỳ chỉnh. Nếu lớp View của bạn được định nghĩa bên trong 1 lớp khác, bạn phải khai báo đầy đủ cả tên của lớp bên ngoài.

Ví dụ nếu lớp PieChart là một lớp được định nghĩa bên trong của lớp PieView. Để sự dụng các thuộc tính tuỳ chỉnh từ lớp này, bạn khai báo như sau: com.example.customviews.charting.PieChart$PieView.

**Áp dụng các tuỳ chỉnh thuộc tính **

Khi một View được tạo ra từ các bố trí XML, tất cả các thuộc tính trong thẻ XMl được đọc từ một gói tài nguyên và thông qua hàm khởi tại của View với đối số AttributeSet. Mặc dù nó có thể đọc các giá trị trực tiếp từ AttributeSet, nhưng làm như vậy cố một số nhược điểm sau:

  • Các tài nguyên được ảnh xạ trong các giá trị thuộc tính là không được giải quyết

  • Các định kiểu (style) là không được áp dụng

Thay vào đó đưa AttributeSet tới obtainStyledAttributes () . Phương pháp này sẽ trả lại một mảng giá trị TypedArray đã được ánh xạ và định kiểu. Đây là cách lớp PieChart đọc các thuộc tính của nó.

Trình biên dịch Android thực hiện rất nhiều công việc để bạn thực hiện cuộc gọi obtainStyledAttributes (). dễ dàng hơn. Đối với mỗi thành phần <declare-styleable> trong thư mục res, lớp R.java tự tạo ra một mảng các thuộc tính ids và tập hợp các hằng số xác định các chỉ số cho từng thuộc tính trong mảng. Bạn sử dụng các hằng số được xác định trước để đọc các thuộc tính từ TypedArray. Đây là các lớp PieChart đọc các thuộc tính của nó.

public PieChart(Context context, AttributeSet attrs) {
   super(context, attrs);
   TypedArray a = context.getTheme().obtainStyledAttributes(
        attrs,
        R.styleable.PieChart,
        0, 0);

   try {
       mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
       mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
   } finally {
       a.recycle();
   }
}

Lưu ý đối tượng TypedArray là một tài nguyên được chỉa sẻ nên phải được giải phóng (recycle ) sau khi sử dụng.

Thêm các thuộc tính và sự kiện (Properties and Events)

Thuộc tính là một cách để kiểm soát hành vi và sự xuất hiện của các View, nhưng nó chỉ được đọc khi View được khởi tạo. Để cung cấp các phương thức sử dụng cặp phương thức getter và setter cho mỗi thuộc tính tuỳ chỉnh. Đây là cách mà PieChart gọi thuộc tính showText:

public boolean isShowText() {
   return mShowText;
}

public void setShowText(boolean showText) {
   mShowText = showText;
   invalidate();
   requestLayout();
}

Chú ý rằng setShowText gọi invalidate()requestLayout(). Những cuộc gọi này là rất quan trọng để đảm bảo các hành vi đáp ứng lại một cách chính xác. Bạn sử dụng invalidate sau khi có bất kỳ thay đổi thuộc tính nào để thay đổi sự xuất hiện của nó, sau đó hệ thống biết rằng nó cần được vẽ lại. Tương tự như vậy, bạn cần phải yêu cầu bố trí mới (requestLayout) nếu một thuộc tính thay đổi có thể ảnh hưởng đến kích thước hoặc hình dạng của View. Quên gọi các phương thức này có thể gây khó khăn cho bạn khi debug chương trình.

Tuỳ biến Views cũng nên hộ trợ các sự kiện để lắng nghe các hành động quan trọng. Ví dụ, PieChart đưa ra một sự kiện tuỳ chỉnh được gọi là OnCurrentItemChanged để thông báo rằng người dùng đã quay biểu đồ hình tròn.

Sample Codes

Download: Tại Đây

Screenshot:

PieChart


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.