Tiện ích ứng dụng là các thành phần hiển thị thu nhỏ của ứng dụng mà bạn có thể nhúng vào các ứng dụng khác (chẳng hạn như màn hình chính) và nhận thông tin cập nhật định kỳ. Các thành phần hiển thị này được gọi là tiện ích trong giao diện người dùng và bạn có thể phát hành một tiện ích bằng trình cung cấp tiện ích ứng dụng (hoặc trình cung cấp tiện ích). Thành phần ứng dụng chứa các tiện ích khác được gọi là máy chủ tiện ích ứng dụng (hoặc máy chủ tiện ích). Hình 1 cho thấy một tiện ích nhạc mẫu:
Tài liệu này mô tả cách xuất bản tiện ích bằng cách sử dụng nhà cung cấp tiện ích. Để biết thêm thông tin chi tiết về cách tạo AppWidgetHost
của riêng bạn nhằm lưu trữ tiện ích ứng dụng, hãy xem phần Tạo máy chủ tiện ích.
Để biết thông tin về cách thiết kế tiện ích, hãy xem nội dung Tổng quan về tiện ích ứng dụng.
Thành phần tiện ích
Để tạo một tiện ích, bạn cần có các thành phần cơ bản sau:
- Đối tượng
AppWidgetProviderInfo
- Mô tả siêu dữ liệu cho một tiện ích, chẳng hạn như bố cục của tiện ích, tần suất cập nhật và lớp
AppWidgetProvider
.AppWidgetProviderInfo
được định nghĩa trong XML, như mô tả trong tài liệu này. - Lớp
AppWidgetProvider
- Xác định các phương thức cơ bản cho phép bạn lập trình giao diện bằng tiện ích. Thông qua đó, bạn sẽ nhận được thông báo truyền tin khi tiện ích được cập nhật, bật, tắt hoặc xoá. Bạn khai báo
AppWidgetProvider
trong tệp kê khai, sau đó triển khai tệp kê khai đó, như mô tả trong tài liệu này. - Bố cục chế độ xem
- Xác định bố cục ban đầu cho tiện ích. Bố cục được xác định trong XML, như mô tả trong tài liệu này.
Hình 2 cho thấy cách các thành phần này phù hợp với quy trình xử lý tiện ích ứng dụng tổng thể.
Nếu tiện ích của bạn cần người dùng định cấu hình, hãy triển khai hoạt động định cấu hình tiện ích ứng dụng. Hoạt động này cho phép người dùng sửa đổi chế độ cài đặt tiện ích, chẳng hạn như múi giờ cho tiện ích đồng hồ.
- Kể từ Android 12 (API cấp 31), bạn có thể cung cấp cấu hình mặc định và cho phép người dùng định cấu hình lại tiện ích vào lúc khác. Xem phần Sử dụng cấu hình mặc định của tiện ích và Cho phép người dùng định cấu hình lại các tiện ích đã đặt để biết thêm thông tin chi tiết.
- Trong Android 11 (API cấp 30) trở xuống, hoạt động này được khởi chạy mỗi khi người dùng thêm tiện ích vào màn hình chính.
Bạn cũng nên cải tiến những điểm sau: bố cục tiện ích linh hoạt, các tính năng nâng cao khác, tiện ích nâng cao, tiện ích bộ sưu tập và tạo máy chủ lưu trữ tiện ích.
Khai báo tệp XML AppWidgetProviderInfo
Đối tượng AppWidgetProviderInfo
xác định các phẩm chất thiết yếu của một tiện ích.
Xác định đối tượng AppWidgetProviderInfo
trong tệp tài nguyên XML bằng một phần tử <appwidget-provider>
và lưu đối tượng đó vào thư mục res/xml/
của dự án.
Lệnh này được minh hoạ trong ví dụ sau:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="40dp"
android:minHeight="40dp"
android:targetCellWidth="1"
android:targetCellHeight="1"
android:maxResizeWidth="250dp"
android:maxResizeHeight="120dp"
android:updatePeriodMillis="86400000"
android:description="@string/example_appwidget_description"
android:previewLayout="@layout/example_appwidget_preview"
android:initialLayout="@layout/example_loading_appwidget"
android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen"
android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>
Thuộc tính định kích thước tiện ích
Màn hình chính mặc định sẽ xác định vị trí của các tiện ích trong cửa sổ đó dựa trên một lưới các ô có chiều cao và chiều rộng đã xác định. Hầu hết màn hình chính chỉ cho phép các tiện ích có kích thước là bội số nguyên của các ô lưới, ví dụ: 2 ô theo chiều ngang và 3 ô theo chiều dọc.
Các thuộc tính kích thước tiện ích cho phép bạn chỉ định một kích thước mặc định cho tiện ích, đồng thời cung cấp các giới hạn dưới và giới hạn trên của kích thước tiện ích đó. Trong ngữ cảnh này, kích thước mặc định của tiện ích là kích thước mà tiện ích đó có khi được thêm vào màn hình chính lần đầu tiên.
Bảng sau đây mô tả các thuộc tính <appwidget-provider>
liên quan đến việc định cỡ tiện ích:
Thuộc tính và nội dung mô tả | |
---|---|
targetCellWidth và
targetCellHeight (Android 12),
minWidth và minHeight |
targetCellWidth và targetCellHeight , cũng như minWidth và minHeight – để ứng dụng của bạn có thể quay lại sử dụng minWidth và minHeight nếu thiết bị của người dùng không hỗ trợ targetCellWidth và targetCellHeight . Nếu được hỗ trợ, các thuộc tính targetCellWidth và targetCellHeight sẽ được ưu tiên hơn các thuộc tính minWidth và minHeight .
|
minResizeWidth và
minResizeHeight |
Chỉ định kích thước tối thiểu tuyệt đối của tiện ích. Các giá trị này chỉ định kích thước mà tiện ích không đọc được hoặc không sử dụng được. Việc sử dụng các thuộc tính này cho phép người dùng đổi kích thước tiện ích thành kích thước nhỏ hơn kích thước tiện ích mặc định. Thuộc tính minResizeWidth sẽ bị bỏ qua nếu lớn hơn minWidth hoặc nếu bạn không bật tính năng đổi kích thước theo chiều ngang. Xem resizeMode . Tương tự, thuộc tính minResizeHeight sẽ bị bỏ qua nếu lớn hơn minHeight hoặc nếu bạn không bật tính năng đổi kích thước theo chiều dọc. |
maxResizeWidth và
maxResizeHeight |
Chỉ định kích thước tối đa được đề xuất cho tiện ích. Nếu các giá trị không phải là bội số của kích thước ô lưới, thì các giá trị đó sẽ được làm tròn lên kích thước ô gần nhất. Thuộc tính maxResizeWidth sẽ bị bỏ qua nếu nhỏ hơn minWidth hoặc nếu bạn không bật tính năng đổi kích thước theo chiều ngang. Xem resizeMode . Tương tự, thuộc tính maxResizeHeight sẽ bị bỏ qua nếu lớn hơn minHeight hoặc nếu bạn không bật tính năng đổi kích thước theo chiều dọc.
Ra mắt trong Android 12. |
resizeMode |
Chỉ định các quy tắc để có thể đổi kích thước tiện ích. Bạn có thể sử dụng thuộc tính này để tạo các tiện ích trên màn hình chính có thể đổi kích thước theo chiều ngang, chiều dọc hoặc trên cả hai trục. Người dùng chạm và giữ một tiện ích để hiện ô điều khiển thay đổi kích thước, sau đó kéo ô điều khiển theo chiều ngang hoặc chiều dọc để thay đổi kích thước trên lưới bố cục. Các giá trị cho thuộc tính resizeMode bao gồm horizontal , vertical và none . Để khai báo một tiện ích có thể đổi kích thước theo chiều ngang và chiều dọc, hãy sử dụng horizontal|vertical . |
Ví dụ
Để minh hoạ cách các thuộc tính trong bảng trước ảnh hưởng đến việc định cỡ tiện ích, hãy giả định các thông số kỹ thuật sau:
- Ô lưới có chiều rộng 30 dp và chiều cao 50 dp.
- Chúng tôi cung cấp thông số kỹ thuật thuộc tính sau:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="80dp"
android:minHeight="80dp"
android:targetCellWidth="2"
android:targetCellHeight="2"
android:minResizeWidth="40dp"
android:minResizeHeight="40dp"
android:maxResizeWidth="120dp"
android:maxResizeHeight="120dp"
android:resizeMode="horizontal|vertical" />
Kể từ Android 12:
Sử dụng thuộc tính targetCellWidth
và targetCellHeight
làm kích thước mặc định của tiện ích.
Kích thước của tiện ích là 2x2 theo mặc định. Bạn có thể đổi kích thước tiện ích xuống 2x1 hoặc lên đến 4x3.
Android 11 trở xuống:
Sử dụng thuộc tính minWidth
và minHeight
để tính toán kích thước mặc định của tiện ích.
Chiều rộng mặc định = Math.ceil(80 / 30)
= 3
Chiều cao mặc định = Math.ceil(80 / 50)
= 2
Kích thước của tiện ích là 3x2 theo mặc định. Bạn có thể đổi kích thước tiện ích xuống 2x1 hoặc lên đến toàn màn hình.
Các thuộc tính tiện ích bổ sung
Bảng sau đây mô tả các thuộc tính <appwidget-provider>
liên quan đến các chất lượng khác ngoài việc định cỡ tiện ích.
Thuộc tính và nội dung mô tả | |
---|---|
updatePeriodMillis |
Xác định tần suất khung tiện ích yêu cầu cập nhật từ AppWidgetProvider bằng cách gọi phương thức gọi lại onUpdate() . Việc cập nhật thực tế không đảm bảo sẽ diễn ra chính xác đúng thời gian với giá trị này. Bạn nên cập nhật ít nhất có thể (tối đa một lần mỗi giờ) để tiết kiệm pin.
Để xem danh sách đầy đủ các yếu tố cần cân nhắc nhằm chọn khoảng thời gian cập nhật thích hợp, hãy xem bài viết Tối ưu hoá để cập nhật nội dung tiện ích. |
initialLayout |
Trỏ đến tài nguyên bố cục xác định bố cục tiện ích. |
configure |
Xác định hoạt động khởi chạy khi người dùng thêm tiện ích, cho phép họ định cấu hình các thuộc tính tiện ích. Hãy xem phần Cho phép người dùng định cấu hình tiện ích. Kể từ Android 12, ứng dụng của bạn có thể bỏ qua cấu hình ban đầu. Hãy xem phần Sử dụng cấu hình mặc định của tiện ích để biết thông tin chi tiết. |
description |
Chỉ định nội dung mô tả cho bộ chọn tiện ích để hiển thị cho tiện ích của bạn. Ra mắt trong Android 12. |
previewLayout (Android 12)
và previewImage (Android 11 trở xuống) |
previewImage và previewLayout để ứng dụng có thể quay lại sử dụng previewImage nếu thiết bị của người dùng không hỗ trợ previewLayout . Để biết thêm thông tin, hãy xem phần Khả năng tương thích ngược với bản xem trước tiện ích có thể mở rộng.
|
autoAdvanceViewId |
Chỉ định mã nhận dạng khung hiển thị của thành phần hiển thị phụ của tiện ích được máy chủ của tiện ích tự động nâng cấp. |
widgetCategory |
Khai báo xem tiện ích của bạn có thể hiển thị trên màn hình chính (home_screen ), màn hình khoá (keyguard ) hay cả hai không. Đối với Android 5.0 trở lên, chỉ home_screen là hợp lệ.
|
widgetFeatures |
Khai báo các tính năng mà tiện ích hỗ trợ. Ví dụ: nếu bạn muốn tiện ích của mình sử dụng cấu hình mặc định khi người dùng thêm tiện ích đó, hãy chỉ định cả cờ configuration_optional và reconfigurable . Thao tác này sẽ bỏ qua việc khởi chạy hoạt động định cấu hình sau khi người dùng thêm tiện ích. Sau đó, người dùng vẫn có thể định cấu hình lại tiện ích. |
Sử dụng lớp AppWidgetProvider để xử lý thông báo truyền tin tiện ích
Lớp AppWidgetProvider
xử lý thông báo truyền tin tiện ích và cập nhật tiện ích để phản hồi các sự kiện trong vòng đời của tiện ích. Các phần sau đây mô tả cách khai báo AppWidgetProvider
trong tệp kê khai rồi triển khai tệp đó.
Khai báo tiện ích trong tệp kê khai
Trước tiên, hãy khai báo lớp AppWidgetProvider
trong tệp AndroidManifest.xml
của ứng dụng như trong ví dụ sau:
<receiver android:name="ExampleAppWidgetProvider"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/example_appwidget_info" />
</receiver>
Phần tử <receiver>
yêu cầu thuộc tính android:name
. Thuộc tính này chỉ định AppWidgetProvider
mà tiện ích sử dụng. Bạn không được xuất thành phần này trừ phi có một quy trình riêng cần truyền tin tới AppWidgetProvider
(thường không đúng như vậy).
Phần tử <intent-filter>
phải bao gồm một phần tử <action>
có thuộc tính android:name
. Thuộc tính này chỉ định rằng AppWidgetProvider
chấp nhận thông báo truyền tin ACTION_APPWIDGET_UPDATE
. Đây là thông báo truyền tin duy nhất mà bạn phải khai báo rõ ràng. AppWidgetManager
tự động gửi mọi thông báo về tiện ích khác tới AppWidgetProvider
nếu cần.
Phần tử <meta-data>
chỉ định tài nguyên AppWidgetProviderInfo
và yêu cầu các thuộc tính sau:
android:name
: chỉ định tên siêu dữ liệu. Sử dụngandroid.appwidget.provider
để xác định dữ liệu dưới dạng chỉ số mô tảAppWidgetProviderInfo
.android:resource
: chỉ định vị trí tài nguyênAppWidgetProviderInfo
.
Triển khai lớp AppWidgetProvider
Lớp AppWidgetProvider
mở rộng BroadcastReceiver
làm lớp tiện lợi để xử lý các thông báo truyền tin tiện ích. Trình nghe này chỉ nhận được các thông báo truyền tin sự kiện liên quan đến tiện ích, chẳng hạn như khi tiện ích được cập nhật, xoá, bật và tắt. Khi các sự kiện truyền tin này xảy ra, các phương thức AppWidgetProvider
sau đây sẽ được gọi:
onUpdate()
- Lệnh gọi này được gọi để cập nhật tiện ích tại các khoảng thời gian do thuộc tính
updatePeriodMillis
trongAppWidgetProviderInfo
xác định. Hãy xem bảng mô tả các thuộc tính tiện ích bổ sung trong trang này để biết thêm thông tin. - Phương thức này cũng được gọi khi người dùng thêm tiện ích, vì vậy, phương thức này sẽ thực hiện các bước thiết lập cần thiết như xác định trình xử lý sự kiện cho các đối tượng
View
hoặc bắt đầu công việc để tải dữ liệu hiển thị trong tiện ích. Tuy nhiên, nếu bạn khai báo một hoạt động cấu hình mà không có cờconfiguration_optional
, thì phương thức này không được gọi khi người dùng thêm tiện ích, nhưng được gọi cho các bản cập nhật tiếp theo. Hoạt động cấu hình có trách nhiệm thực hiện lần cập nhật đầu tiên khi cấu hình hoàn tất. Hãy xem phần Cho phép người dùng định cấu hình tiện ích ứng dụng để biết thêm thông tin. - Lệnh gọi lại quan trọng nhất là
onUpdate()
. Hãy xem phần Xử lý sự kiện bằng lớponUpdate()
trong trang này để biết thêm thông tin. onAppWidgetOptionsChanged()
Phương thức này được gọi khi đặt tiện ích lần đầu tiên và mỗi khi tiện ích được đổi kích thước. Sử dụng lệnh gọi lại này để hiển thị hoặc ẩn nội dung dựa trên phạm vi kích thước của tiện ích. Lấy phạm vi kích thước và kể từ Android 12, danh sách các kích thước mà một thực thể tiện ích có thể có thể sử dụng bằng cách gọi
getAppWidgetOptions()
. Lệnh này sẽ trả về mộtBundle
bao gồm:OPTION_APPWIDGET_MIN_WIDTH
: chứa giới hạn dưới của chiều rộng, tính bằng đơn vị dp, của một thực thể tiện ích.OPTION_APPWIDGET_MIN_HEIGHT
: chứa giới hạn dưới của chiều cao, tính bằng đơn vị dp, của một thực thể tiện ích.OPTION_APPWIDGET_MAX_WIDTH
: chứa giới hạn trên về chiều rộng, tính bằng đơn vị dp, của một thực thể tiện ích.OPTION_APPWIDGET_MAX_HEIGHT
: chứa giới hạn trên của chiều cao, tính bằng đơn vị dp, của một thực thể tiện ích.OPTION_APPWIDGET_SIZES
: chứa danh sách các kích thước có thể sử dụng (List<SizeF>
), theo đơn vị dp mà một thực thể tiện ích có thể nhận. Ra mắt trong Android 12.
onDeleted(Context, int[])
Phương thức này được gọi mỗi khi một tiện ích bị xoá khỏi máy chủ tiện ích.
onEnabled(Context)
Lệnh này được gọi khi một thực thể của tiện ích được tạo lần đầu tiên. Ví dụ: nếu người dùng thêm hai thực thể của tiện ích, thì tiện ích này chỉ được gọi lần đầu tiên. Nếu bạn cần mở một cơ sở dữ liệu mới hoặc thực hiện một chế độ thiết lập khác chỉ cần thực hiện một lần cho tất cả các thực thể tiện ích, thì đây là một nơi phù hợp để thực hiện việc này.
onDisabled(Context)
Phương thức này được gọi khi thực thể cuối cùng của tiện ích bị xoá khỏi máy chủ tiện ích. Đây là nơi bạn dọn dẹp mọi công việc đã thực hiện trong
onEnabled(Context)
, chẳng hạn như xoá cơ sở dữ liệu tạm thời.onReceive(Context, Intent)
Lệnh này được gọi cho mọi thông báo truyền tin và trước mỗi phương thức gọi lại trước đó. Thông thường, bạn không cần triển khai phương thức này vì phương thức triển khai
AppWidgetProvider
mặc định sẽ lọc tất cả thông báo truyền tin tiện ích và gọi các phương thức trước đó khi thích hợp.
Bạn phải khai báo quá trình triển khai lớp AppWidgetProvider
dưới dạng broadcast receiver bằng cách sử dụng phần tử <receiver>
trong AndroidManifest
. Hãy xem phần Khai báo tiện ích trong tệp kê khai trên trang này để biết thêm thông tin.
Xử lý sự kiện bằng lớp onUpdate()
Lệnh gọi lại AppWidgetProvider
quan trọng nhất là onUpdate()
vì lệnh này được gọi khi mỗi tiện ích được thêm vào máy chủ, trừ phi bạn sử dụng một hoạt động cấu hình không có cờ configuration_optional
. Nếu tiện ích của bạn chấp nhận bất kỳ sự kiện tương tác nào của người dùng, hãy đăng ký trình xử lý sự kiện trong lệnh gọi lại này. Nếu tiện ích của bạn không tạo tệp hoặc cơ sở dữ liệu tạm thời hoặc thực hiện công việc khác cần dọn dẹp, thì onUpdate()
có thể là phương thức gọi lại duy nhất bạn cần xác định.
Ví dụ: nếu muốn một tiện ích có nút chạy một hoạt động khi người dùng nhấn vào, bạn có thể sử dụng cách triển khai AppWidgetProvider
sau:
Kotlin
class ExampleAppWidgetProvider : AppWidgetProvider() { override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) { // Perform this loop procedure for each widget that belongs to this // provider. appWidgetIds.forEach { appWidgetId -> // Create an Intent to launch ExampleActivity. val pendingIntent: PendingIntent = PendingIntent.getActivity( /* context = */ context, /* requestCode = */ 0, /* intent = */ Intent(context, ExampleActivity::class.java), /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // Get the layout for the widget and attach an onClick listener to // the button. val views: RemoteViews = RemoteViews( context.packageName, R.layout.appwidget_provider_layout ).apply { setOnClickPendingIntent(R.id.button, pendingIntent) } // Tell the AppWidgetManager to perform an update on the current // widget. appWidgetManager.updateAppWidget(appWidgetId, views) } } }
Java
public class ExampleAppWidgetProvider extends AppWidgetProvider { public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // Perform this loop procedure for each widget that belongs to this // provider. for (int i=0; i < appWidgetIds.length; i++) { int appWidgetId = appWidgetIds[i]; // Create an Intent to launch ExampleActivity Intent intent = new Intent(context, ExampleActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity( /* context = */ context, /* requestCode = */ 0, /* intent = */ intent, /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); // Get the layout for the widget and attach an onClick listener to // the button. RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget_layout); views.setOnClickPendingIntent(R.id.button, pendingIntent); // Tell the AppWidgetManager to perform an update on the current app // widget. appWidgetManager.updateAppWidget(appWidgetId, views); } } }
AppWidgetProvider
này chỉ xác định phương thức onUpdate()
, sử dụng phương thức này để tạo PendingIntent
chạy Activity
và đính kèm vào nút của tiện ích bằng setOnClickPendingIntent(int,
PendingIntent)
. Phương thức này bao gồm một vòng lặp lặp lại từng mục nhập trong appWidgetIds
. Đây là một mảng gồm các mã nhận dạng xác định từng tiện ích do nhà cung cấp này tạo. Nếu người dùng tạo nhiều phiên bản của tiện ích, thì tất cả các phiên bản đó sẽ cập nhật đồng thời. Tuy nhiên, chỉ có một lịch biểu updatePeriodMillis
được quản lý cho tất cả các thực thể của tiện ích. Ví dụ: nếu lịch cập nhật được xác định là 2 giờ một lần và một thực thể thứ hai của tiện ích được thêm vào một giờ sau thực thể đầu tiên, thì cả hai thực thể này đều được cập nhật theo khoảng thời gian do thực thể đầu tiên xác định và khoảng thời gian cập nhật thứ hai sẽ bị bỏ qua. Cả hai đều cập nhật 2 giờ một lần, chứ không phải mỗi giờ.
Hãy xem lớp mẫu ExampleAppWidgetProvider.java
để biết thêm chi tiết.
Nhận ý định truyền tin tiện ích
AppWidgetProvider
là một lớp tiện lợi. Nếu muốn trực tiếp nhận thông báo truyền tin tiện ích, bạn có thể triển khai BroadcastReceiver
của riêng mình hoặc ghi đè lệnh gọi lại onReceive(Context,Intent)
. Sau đây là những ý định mà bạn cần quan tâm:
ACTION_APPWIDGET_UPDATE
ACTION_APPWIDGET_DELETED
ACTION_APPWIDGET_ENABLED
ACTION_APPWIDGET_DISABLED
ACTION_APPWIDGET_OPTIONS_CHANGED
Tạo bố cục tiện ích
Bạn phải xác định bố cục ban đầu cho tiện ích của mình trong XML và lưu bố cục đó vào thư mục res/layout/
của dự án. Tham khảo Nguyên tắc thiết kế để biết thông tin chi tiết.
Việc tạo bố cục tiện ích rất đơn giản nếu bạn đã quen thuộc với bố cục. Tuy nhiên, hãy lưu ý rằng bố cục tiện ích dựa trên RemoteViews
không hỗ trợ mọi loại bố cục hoặc tiện ích thành phần hiển thị. Bạn không thể sử dụng khung hiển thị tuỳ chỉnh hoặc lớp con của khung hiển thị được RemoteViews
hỗ trợ.
RemoteViews
cũng hỗ trợ ViewStub
, đây là một View
vô hình, có kích thước bằng 0 mà bạn có thể sử dụng để tăng cường từng phần tài nguyên bố cục trong thời gian chạy.
Hỗ trợ hành vi có trạng thái
Android 12 hỗ trợ thêm hành vi có trạng thái bằng cách sử dụng các thành phần hiện có sau:
Tiện ích vẫn không có trạng thái. Ứng dụng của bạn phải lưu trữ trạng thái và đăng ký các sự kiện thay đổi trạng thái.
Mã ví dụ sau đây cho biết cách triển khai các thành phần này.
Kotlin
// Check the view. remoteView.setCompoundButtonChecked(R.id.my_checkbox, true) // Check a radio group. remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2) // Listen for check changes. The intent has an extra with the key // EXTRA_CHECKED that specifies the current checked state of the view. remoteView.setOnCheckedChangeResponse( R.id.my_checkbox, RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent) )
Java
// Check the view. remoteView.setCompoundButtonChecked(R.id.my_checkbox, true); // Check a radio group. remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2); // Listen for check changes. The intent has an extra with the key // EXTRA_CHECKED that specifies the current checked state of the view. remoteView.setOnCheckedChangeResponse( R.id.my_checkbox, RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent));
Cung cấp hai bố cục: một bố cục nhắm đến các thiết bị chạy Android 12 trở lên trong res/layout-v31
và bố cục còn lại nhắm đến Android 11 trở xuống trong thư mục res/layout
mặc định.
Triển khai góc bo tròn
Android 12 giới thiệu các thông số hệ thống sau đây để đặt bán kính của các góc bo tròn của tiện ích:
system_app_widget_background_radius
: bán kính góc của nền tiện ích, không bao giờ lớn hơn 28 dp.system_app_widget_inner_radius
: bán kính góc của bất kỳ thành phần hiển thị nào bên trong tiện ích. Đây là khoảng cách chính xác 8 dp nhỏ hơn bán kính nền để căn chỉnh đẹp mắt khi sử dụng khoảng đệm 8 dp.
Ví dụ sau đây cho thấy một tiện ích sử dụng system_app_widget_background_radius
cho góc của tiện ích và system_app_widget_inner_radius
cho các thành phần hiển thị bên trong tiện ích.
1 Góc của tiện ích.
2 Góc của thành phần hiển thị bên trong tiện ích.
Những điểm cần lưu ý quan trọng về góc bo tròn
- Trình chạy và nhà sản xuất thiết bị của bên thứ ba có thể ghi đè tham số
system_app_widget_background_radius
thành kích thước nhỏ hơn 28 dp. Tham sốsystem_app_widget_inner_radius
luôn nhỏ hơn 8 dp so với giá trị củasystem_app_widget_background_radius
. - Nếu tiện ích của bạn không sử dụng
@android:id/background
hoặc xác định nền cắt nội dung của tiện ích dựa trên đường viền (vớiandroid:clipToOutline
được đặt thànhtrue
), thì trình chạy sẽ tự động xác định nền và cắt tiện ích bằng hình chữ nhật có các góc bo tròn lên đến 16 dp. Xem phần Đảm bảo tiện ích của bạn tương thích với Android 12.
Để tiện ích tương thích với các phiên bản Android trước, bạn nên xác định các thuộc tính tuỳ chỉnh và sử dụng giao diện tuỳ chỉnh để ghi đè các thuộc tính đó cho Android 12, như trong các tệp XML mẫu sau:
/values/attrs.xml
<resources>
<attr name="backgroundRadius" format="dimension" />
</resources>
/values/styles.xml
<resources>
<style name="MyWidgetTheme">
<item name="backgroundRadius">@dimen/my_background_radius_dimen</item>
</style>
</resources>
/values-31/styles.xml
<resources>
<style name="MyWidgetTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
<item name="backgroundRadius">@android:dimen/system_app_widget_background_radius</item>
</style>
</resources>
/drawable/my_widget_background.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="?attr/backgroundRadius" />
...
</shape>
/layout/my_widget_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
android:background="@drawable/my_widget_background" />