tệp kê khai, siêu dữ liệu
Các phần sau đây mô tả cách tạo một tiện ích cơ bản cho ứng dụng bằng Glance.
Khai báo AppWidget trong tệp kê khai
Sau khi hoàn tất các bước thiết lập, hãy khai báo AppWidget và siêu dữ liệu của nó trong ứng dụng.
Mở rộng bộ nhận
AppWidgettừGlanceAppWidgetReceiver:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget = TODO("Create GlanceAppWidget") }
Đăng ký nhà cung cấp tiện ích ứng dụng trong tệp
AndroidManifest.xmlvà tệp siêu dữ liệu được liên kết:<receiver android:name=".glance.MyReceiver" android:exported="true"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/my_app_widget_info" /> </receiver>
Thêm siêu dữ liệu AppWidgetProviderInfo
Tiếp theo, hãy làm theo hướng dẫn Tạo một tiện ích để tạo và xác định thông tin tiện ích ứng dụng trong tệp @xml/my_app_widget_info.
Điểm khác biệt duy nhất đối với Glance là không có tệp XML initialLayout, nhưng bạn phải xác định một tệp. Bạn có thể sử dụng bố cục tải được xác định trước có trong thư viện:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/glance_default_loading_layout">
</appwidget-provider>
Khai báo XML AppWidgetProviderInfo
Đối tượng AppWidgetProviderInfo xác định những đặc điểm thiết yếu của tiện ích. Xác định AppWidgetProviderInfo trong tệp tài nguyên siêu dữ liệu XML (res/xml/my_app_widget_info.xml) bên trong phần tử <appwidget-provider>:
<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/glance_default_loading_layout"
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 cỡ tiện ích
Màn hình chính mặc định sẽ đặt các tiện ích vào cửa sổ dựa trên một lưới ô 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 định cỡ tiện ích cho phép bạn chỉ định kích thước mặc định cho tiện ích và cung cấp giới hạn dưới và trên về kích thước của 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 sẽ 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à theo đó tiện ích không đọc được hoặc không sử dụng được. Khi sử dụng các thuộc tính này, người dùng có thể đổi kích thước tiện ích thành kích thước nhỏ hơn kích thước mặc định của tiện ích. 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 phần 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 của 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 đế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. Hãy xem resizeMode. Tương tự, thuộc tính maxResizeHeight sẽ bị bỏ qua nếu nhỏ 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 mà theo đó, bạn có thể đổi kích thước một tiện ích. Bạn có thể dùng thuộc tính này để thay đổi kích thước tiện ích trên màn hình chính 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 các ô điều khiển thay đổi kích thước, sau đó kéo các ô điều khiển ngang hoặc dọc để thay đổi kích thước của tiện ích 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:
- Một ô lưới có chiều rộng 30 dp và chiều cao 50 dp.
- Sau đây là quy cách thuộc tính được cung cấp:
<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" />
Bắt đầu 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.
Theo mặc định, kích thước của tiện ích là 2x2. Bạn có thể giảm kích thước tiện ích xuống 2x1 hoặc tăng lên 4x3.
Android 11 trở xuống:
Sử dụng các thuộc tính minWidth và minHeight để tính toán kích thước mặc định của tiện ích.
Độ rộng mặc định = Math.ceil(80 / 30) = 3
Chiều cao mặc định = Math.ceil(80 / 50) = 2
Theo mặc định, kích thước của tiện ích là 3x2. Bạn có thể giảm kích thước của tiện ích xuống 2x1 hoặc tăng lên toàn màn hình.
Các thuộc tính bổ sung của tiện ích
Bảng sau đây mô tả các thuộc tính <appwidget-provider> liên quan đến các yếu tố 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ừ GlanceAppWidgetReceiver bằng cách gọi phương thức gọi lại onUpdate(). Bạn nên cập nhật ít thường xuyên nhất có thể (không quá một lần mỗi giờ) để tiết kiệm pin.
Để biết thông tin chi tiết, hãy xem phần Thời điểm cập nhật tiện ích trong bài viết Quản lý trạng thái Glance. |
initialLayout |
Chỉ đến tài nguyên bố cục xác định bố cục tải của tiện ích trước khi các thành phần giao diện người dùng Glance kết xuất. Bạn có thể sử dụng bố cục tải được xác định trước có trong thư viện: @layout/glance_default_loading_layout. |
configure |
Xác định hoạt động định cấu hình sẽ chạy khi người dùng thêm tiện ích. Hãy xem phần Triển khai một Hoạt động định cấu hình tiện ích trên trang này. |
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) |
|
autoAdvanceViewId |
Chỉ định mã nhận dạng khung hiển thị của khung hiển thị phụ của tiện ích do máy chủ của tiện ích tự động chuyển. |
widgetCategory |
Khai báo xem tiện ích của bạn có thể xuất hiện trên màn hình chính (home_screen), màn hình khoá (keyguard) hay cả hai. Đối với Android 5.0 trở lên, chỉ home_screen mới hợp lệ. |
widgetFeatures |
Khai báo các tính năng mà tiện ích hỗ trợ. Ví dụ: nếu cấu hình tiện ích của bạn là không bắt buộc, hãy chỉ định cả configuration_optional và reconfigurable. |
Xác định GlanceAppWidget
Tạo một lớp mới mở rộng từ
GlanceAppWidgetvà ghi đè phương thứcprovideGlance. Đây là phương thức mà bạn có thể tải dữ liệu cần thiết để hiển thị tiện ích:class MyAppWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId) { // In this method, load data needed to render the AppWidget. // Use `withContext` to switch to another thread for long running // operations. provideContent { // create your AppWidget here Text("Hello World") } } }
Tạo thực thể cho nó trong
glanceAppWidgettrênGlanceAppWidgetReceivercủa bạn:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { // Let MyAppWidgetReceiver know which GlanceAppWidget to use override val glanceAppWidget: GlanceAppWidget = MyAppWidget() }
Giờ đây, bạn đã định cấu hình AppWidget bằng Glance.
Sử dụng lớp AppWidgetProvider để xử lý thông báo truyền tin của tiện ích
Tiện ích GlanceAppWidgetReceiver toạ độ phát và cập nhật trạng thái nền tảng bằng cách mở rộng AppWidgetProvider cơ bản. Nó nhận các sự kiện nền tảng khi tiện ích của bạn được cập nhật, xoá, bật hoặc tắt, chuyển đổi các sự kiện đó thành các yêu cầu vòng đời Compose.
Khai báo một tiện ích trong tệp kê khai
Khai báo lớp con GlanceAppWidgetReceiver của bạn làm bộ nhận tín hiệu truyền tin trong tệp AndroidManifest.xml:
<receiver android:name="ExampleAppWidgetReceiver"
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/my_app_widget_info" />
</receiver>
Phần tử <receiver> yêu cầu thuộc tính android:name. Thuộc tính này chỉ định lớp nhận. Receiver phải chấp nhận thao tác truyền tin ACTION_APPWIDGET_UPDATE bên trong <intent-filter>.
Phần tử <meta-data> phải xác định tên của phần tử đó là android.appwidget.provider và thuộc tính android:resource phải trỏ đến tài nguyên siêu dữ liệu XML AppWidgetProviderInfo (@xml/my_app_widget_info).
Triển khai lớp AppWidgetProvider
Trong Glance, bạn mở rộng GlanceAppWidgetReceiver thay vì AppWidgetProvider trực tiếp. Triển khai bằng cách liên kết bộ nhận với phiên bản GlanceAppWidget. Các lệnh gọi lại chính có trong GlanceAppWidgetReceiver hoạt động như sau:
onUpdate(): Tự động bị Glance ghi đè để thực thi các bản cập nhật thành phần. Nếu ghi đèonUpdatetheo cách thủ công, bạn phải gọisuper.onUpdateđể Glance có thể khởi chạy các luồng thành phần một cách thành công.onAppWidgetOptionsChanged(): Được gọi khi tiện ích được đặt hoặc đổi kích thước lần đầu tiên. Gói các mục tuỳ chọn đọc nhanh ở chế độ nền để bố cục của bạn điều chỉnh liền mạch dựa trên các phương diện thời gian chạy.onDeleted(Context, IntArray): Được gọi bất cứ khi nào người dùng xoá một phiên bản tiện ích cụ thể.onEnabled(Context): Kích hoạt khi phiên bản đầu tiên của tiện ích được tạo thành công. Rất phù hợp để chạy các quy trình di chuyển trên toàn cầu.onDisabled(Context): Được gọi khi phiên bản hoạt động gần đây nhất của trình cung cấp bị xoá.onReceive(Context, Intent): Chặn mọi thông báo truyền tin của nền tảng trước các phương thức gọi lại cụ thể. Bạn phải đảm bảo rằng mọi logic của receiver tuỳ chỉnh mà bạn viết đều gọisuper.onReceive(context, intent)và không bao giờ được gọigoAsyncvì Glance tự động định tuyến công việc không đồng bộ.
Nhận ý định truyền tin của tiện ích
Theo cách không rõ ràng, GlanceAppWidgetReceiver sẽ lọc và xử lý các ý định truyền tin cơ bản sau đây của tiện ích nền tảng:
ACTION_APPWIDGET_UPDATEACTION_APPWIDGET_DELETEDACTION_APPWIDGET_ENABLEDACTION_APPWIDGET_DISABLEDACTION_APPWIDGET_OPTIONS_CHANGED
Tạo giao diện người dùng
Đoạn mã sau đây minh hoạ cách tạo giao diện người dùng:
/* Import Glance Composables In the event there is a name clash with the Compose classes of the same name, you may rename the imports per https://kotlinlang.org/docs/packages.html#imports using the `as` keyword. import androidx.glance.Button import androidx.glance.layout.Column import androidx.glance.layout.Row import androidx.glance.text.Text */ class MyAppWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId) { // Load data needed to render the AppWidget. // Use `withContext` to switch to another thread for long running // operations. provideContent { // create your AppWidget here MyContent() } } @Composable private fun MyContent() { Column( modifier = GlanceModifier.fillMaxSize(), verticalAlignment = Alignment.Top, horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = "Where to?", modifier = GlanceModifier.padding(12.dp)) Row(horizontalAlignment = Alignment.CenterHorizontally) { Button( text = "Home", onClick = actionStartActivity<MyActivity>() ) Button( text = "Work", onClick = actionStartActivity<MyActivity>() ) } } } }
Mã mẫu trên thực hiện những việc sau:
- Trong
Columncấp cao nhất, các mục được đặt theo chiều dọc, lần lượt sau nhau. Columnmở rộng kích thước để phù hợp với không gian có sẵn (thông quaGlanceModifier) và căn chỉnh nội dung của không gian đó lên trên cùng (verticalAlignment) và căn giữa theo chiều ngang (horizontalAlignment).- Nội dung của
Columnđược xác định bằng lambda. Thứ tự rất quan trọng.- Mục đầu tiên trong
Columnlà một thành phầnTextcó12.dpkhoảng đệm. - Mục thứ hai là một
Row, trong đó các mục được đặt theo chiều ngang, lần lượt từng mục một, với haiButtonsđược căn giữa theo chiều ngang (horizontalAlignment). Màn hình cuối cùng sẽ phụ thuộc vào không gian có sẵn. Hình ảnh sau đây là một ví dụ về giao diện của thẻ này:
- Mục đầu tiên trong
Bạn có thể thay đổi các giá trị căn chỉnh hoặc áp dụng các giá trị đối tượng sửa đổi khác (chẳng hạn như khoảng đệm) để thay đổi vị trí và kích thước của các thành phần. Hãy xem tài liệu tham khảo để biết danh sách đầy đủ các thành phần, tham số và bộ sửa đổi có sẵn cho từng lớp.
Triển khai góc bo tròn
Android 12 giới thiệu các tham số hệ thống để tuỳ chỉnh bán kính góc của các tiện ích ứng dụng một cách linh hoạt:
system_app_widget_background_radius: Chỉ định bán kính góc của vùng chứa nền tiện ích (không bao giờ lớn hơn 28 dp).- Bán kính bên trong: Để ngăn nội dung bị cắt, hãy tính toán bán kính tỷ lệ cho nội dung bên trong dựa trên đường viền nền hệ thống:
systemRadiusValue - widgetPadding
Trong Glance, bạn có thể áp dụng các thuộc tính định cỡ bán kính góc một cách linh động trong thành phần bằng cách sử dụng GlanceModifier.cornerRadius(android.R.dimen.system_app_widget_background_radius).
Để có khả năng tương thích ngược trên các thiết bị chạy Android 11 (cấp độ API 30) trở xuống, hãy triển khai các thuộc tính tuỳ chỉnh và các giải pháp dự phòng cho tài nguyên giao diện tuỳ chỉnh:
/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>