Một khung hiển thị tuỳ chỉnh được thiết kế kỹ lưỡng cũng giống như bất kỳ lớp nào khác được thiết kế kỹ lưỡng. Nó đóng gói một bộ chức năng cụ thể với giao diện đơn giản, sử dụng CPU và bộ nhớ một cách hiệu quả, v.v. Ngoài việc là một lớp được thiết kế kỹ lưỡng, khung hiển thị tuỳ chỉnh phải thực hiện những việc sau:
- Tuân thủ các tiêu chuẩn của Android.
- Cung cấp các thuộc tính có thể tạo kiểu tuỳ chỉnh hoạt động với bố cục XML của Android.
- Gửi các sự kiện hỗ trợ tiếp cận.
- Tương thích với nhiều nền tảng Android.
Khung Android cung cấp một tập hợp các lớp cơ sở và thẻ XML để giúp bạn tạo một khung hiển thị đáp ứng tất cả các yêu cầu này. Bài học này thảo luận về cách sử dụng khung Android để tạo chức năng cốt lõi của một lớp khung hiển thị.
Bạn có thể tìm thêm thông tin trong bài viết Thành phần khung hiển thị tuỳ chỉnh.
Tạo lớp con cho một khung hiển thị
Tất cả các lớp khung hiển thị được xác định trong khung Android đều mở rộng View. Thành phần hiển thị tuỳ chỉnh của bạn cũng có thể trực tiếp mở rộng View hoặc bạn có thể tiết kiệm thời gian bằng cách mở rộng một trong các lớp con thành phần hiển thị hiện có, chẳng hạn như Button.
Để cho phép Android Studio tương tác với khung hiển thị, tối thiểu bạn phải cung cấp một hàm khởi tạo nhận Context và một đối tượng AttributeSet làm tham số.
Hàm khởi tạo này cho phép trình chỉnh sửa bố cục tạo và chỉnh sửa một thực thể của khung hiển thị.
Kotlin
class PieChart(context: Context, attrs: AttributeSet) : View(context, attrs)
Java
class PieChart extends View { public PieChart(Context context, AttributeSet attrs) { super(context, attrs); } }
Xác định thuộc tính tuỳ chỉnh
Để thêm một View tích hợp vào giao diện người dùng, hãy chỉ định View đó trong một phần tử XML và kiểm soát giao diện cũng như hành vi của View đó bằng các thuộc tính phần tử. Bạn cũng có thể thêm và tạo kiểu cho các khung hiển thị tuỳ chỉnh bằng XML. Để bật hành vi này trong khung hiển thị tuỳ chỉnh, hãy làm như sau:
- Xác định các thuộc tính tuỳ chỉnh cho khung hiển thị của bạn trong một phần tử tài nguyên
<declare-styleable>. - Chỉ định giá trị cho các thuộc tính trong bố cục XML.
- Truy xuất giá trị thuộc tính trong thời gian chạy.
- Áp dụng các giá trị thuộc tính đã truy xuất vào khung hiển thị của bạn.
Phần này trình bày cách xác định các thuộc tính tuỳ chỉnh và chỉ định giá trị của các thuộc tính đó. Phần tiếp theo trình bày cách truy xuất và áp dụng các giá trị tại thời gian chạy.
Để xác định các thuộc tính tuỳ chỉnh, hãy thêm tài nguyên <declare-styleable>
vào dự án của bạn. Theo thông lệ, bạn nên đặt các tài nguyên này vào một tệp res/values/attrs.xml. Sau đây là một ví dụ về tệp 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>
Mã này khai báo 2 thuộc tính tuỳ chỉnh, showText và labelPosition, thuộc về một thực thể có thể tạo kiểu có tên là PieChart. Theo quy ước, tên của thực thể có thể tạo kiểu giống với tên của lớp xác định khung hiển thị tuỳ chỉnh. Mặc dù không bắt buộc phải tuân theo quy ước này, nhưng nhiều trình chỉnh sửa mã phổ biến phụ thuộc vào quy ước đặt tên này để cung cấp tính năng hoàn thành câu lệnh.
Sau khi xác định các thuộc tính tuỳ chỉnh, bạn có thể sử dụng các thuộc tính đó trong tệp XML bố cục giống như các thuộc tính tích hợp. Điểm khác biệt duy nhất là các thuộc tính tuỳ chỉnh của bạn thuộc về một không gian tên khác. Thay vì thuộc về không gian tên http://schemas.android.com/apk/res/android, chúng thuộc về http://schemas.android.com/apk/res/[your package name]. Ví dụ: sau đây là cách sử dụng các thuộc tính được xác định cho 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-auto"> <com.example.customviews.charting.PieChart custom:showText="true" custom:labelPosition="left" /> </LinearLayout>
Để tránh phải lặp lại URI không gian tên dài, mẫu này sử dụng chỉ thị xmlns. Chỉ thị này chỉ định bí danh custom cho không gian tên http://schemas.android.com/apk/res/com.example.customviews.
Bạn có thể chọn bất kỳ biệt hiệu nào bạn muốn cho không gian tên của mình.
Lưu ý tên của thẻ XML thêm khung hiển thị tuỳ chỉnh vào bố cục. Đây là tên đủ điều kiện của lớp khung hiển thị tuỳ chỉnh. Nếu lớp thành phần hiển thị của bạn là một lớp trong, hãy đủ điều kiện hơn nữa bằng tên của lớp ngoài của thành phần hiển thị.
Ví dụ: lớp PieChart có một lớp bên trong tên là PieView. Để sử dụng các thuộc tính tuỳ chỉnh từ lớp này, bạn hãy dùng thẻ com.example.customviews.charting.PieChart$PieView.
Áp dụng thuộc tính tuỳ chỉnh
Khi một thành phần hiển thị được tạo từ bố cục XML, tất cả các thuộc tính trong thẻ XML sẽ được đọc từ gói tài nguyên và được truyền vào hàm khởi tạo của thành phần hiển thị dưới dạng AttributeSet.
Mặc dù bạn có thể đọc trực tiếp các giá trị từ AttributeSet, nhưng việc này có một số nhược điểm:
- Các tham chiếu tài nguyên trong giá trị thuộc tính không được phân giải.
- Không áp dụng được kiểu.
Thay vào đó, hãy truyền AttributeSet đến obtainStyledAttributes().
Phương thức này truyền lại một mảng TypedArray gồm các giá trị đã được huỷ tham chiếu và tạo kiểu.
Trình biên dịch tài nguyên Android sẽ giúp bạn thực hiện nhiều việc để giúp bạn gọi obtainStyledAttributes() dễ dàng hơn. Đối với mỗi tài nguyên <declare-styleable> trong thư mục res/, R.java được tạo sẽ xác định cả một mảng gồm các mã nhận dạng thuộc tính và một tập hợp các hằng số xác định chỉ mục cho từng thuộc tính trong mảng. Bạn dùng các hằng số được xác định trước để đọc các thuộc tính từ TypedArray. Sau đây là cách lớp PieChart đọc các thuộc tính của lớp:
Kotlin
init { context.theme.obtainStyledAttributes( attrs, R.styleable.PieChart, 0, 0).apply { try { mShowText = getBoolean(R.styleable.PieChart_showText, false) textPos = getInteger(R.styleable.PieChart_labelPosition, 0) } finally { recycle() } } }
Java
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); textPos = a.getInteger(R.styleable.PieChart_labelPosition, 0); } finally { a.recycle(); } }
Xin lưu ý rằng các đối tượng TypedArray là một tài nguyên dùng chung và phải được tái chế sau khi sử dụng.
Thêm tài sản và sự kiện
Thuộc tính là một cách hiệu quả để kiểm soát hành vi và giao diện của khung hiển thị, nhưng bạn chỉ có thể đọc các thuộc tính khi khung hiển thị được khởi tạo. Để cung cấp hành vi linh động, hãy hiển thị một cặp phương thức getter và setter thuộc tính cho từng thuộc tính tuỳ chỉnh. Đoạn mã sau đây cho biết cách PieChart hiển thị một thuộc tính có tên là showText:
Kotlin
fun isShowText(): Boolean { return mShowText } fun setShowText(showText: Boolean) { mShowText = showText invalidate() requestLayout() }
Java
public boolean isShowText() { return mShowText; } public void setShowText(boolean showText) { mShowText = showText; invalidate(); requestLayout(); }
Lưu ý rằng setShowText gọi invalidate() và requestLayout(). Những lệnh gọi này rất quan trọng để đảm bảo chế độ xem hoạt động một cách đáng tin cậy. Bạn cần phải vô hiệu hoá khung hiển thị sau khi có bất kỳ thay đổi nào đối với các thuộc tính của khung hiển thị có thể làm thay đổi giao diện của khung hiển thị đó, để hệ thống biết rằng khung hiển thị cần được vẽ lại. Tương tự, bạn cần yêu cầu một bố cục mới nếu một thuộc tính thay đổi theo cách có thể ảnh hưởng đến kích thước hoặc hình dạng của khung hiển thị. Nếu quên gọi các phương thức này, bạn có thể gặp phải những lỗi khó tìm.
Khung hiển thị tuỳ chỉnh cũng phải hỗ trợ trình nghe sự kiện để truyền đạt các sự kiện quan trọng. Ví dụ: PieChart hiển thị một sự kiện tuỳ chỉnh có tên là OnCurrentItemChanged để thông báo cho các trình nghe rằng người dùng đã xoay biểu đồ hình tròn để tập trung vào một lát cắt hình tròn mới.
Bạn rất dễ quên việc hiển thị các thuộc tính và sự kiện, đặc biệt là khi bạn là người dùng duy nhất của khung hiển thị tuỳ chỉnh. Việc dành thời gian để xác định cẩn thận giao diện của khung hiển thị sẽ giúp giảm chi phí bảo trì trong tương lai. Một quy tắc hay mà bạn nên tuân theo là luôn hiển thị mọi thuộc tính ảnh hưởng đến giao diện hoặc hành vi có thể nhìn thấy của khung hiển thị tuỳ chỉnh.
Thiết kế nhằm hỗ trợ khả năng tiếp cận
Khung hiển thị tuỳ chỉnh của bạn phải hỗ trợ nhiều người dùng. Điều này bao gồm cả những người dùng khuyết tật không thể nhìn thấy hoặc sử dụng màn hình cảm ứng. Để hỗ trợ người dùng khuyết tật, hãy làm như sau:
- Gắn nhãn cho các trường nhập bằng thuộc tính
android:contentDescription. - Gửi các sự kiện hỗ trợ tiếp cận bằng cách gọi
sendAccessibilityEvent()khi thích hợp. - Hỗ trợ các bộ điều khiển thay thế, chẳng hạn như bàn phím di chuyển (D-pad) hoặc bi xoay.
Để biết thêm thông tin về cách tạo khung hiển thị hỗ trợ tiếp cận, hãy xem phần Giúp ứng dụng dễ tiếp cận hơn.