Các phần sau đây mô tả cách tạo 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 tiện ích đó trong ứng dụng của bạn.
Mở rộng trình nhận
AppWidgettừGlanceAppWidgetReceiver:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget = TODO("Create GlanceAppWidget") }
Đăng ký nhà cung cấp tiện ích cho ứ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 tiện ích để tạo và xác định thông tin về tiện ích cho ứ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ó XML initialLayout, nhưng bạn phải xác định một XML. 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 các đặ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 kích thước tiện ích
Theo mặc định, màn hình chí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 ô trong 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 kích thước mặc định cho tiện ích và cung cấp các giới hạn dưới và trên về kích thước của tiện ích. Trong bối cảnh này, kích thước mặc định của một 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 kích thướ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ó 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 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 tính năng đổi kích thước theo chiều ngang không được bật. 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 tính năng đổi kích thước theo chiều dọc không được bật. |
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 ô trong 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 tính năng đổi kích thước theo chiều ngang không được bật. Xem resizeMode. Tương tự,
thuộc tính maxResizeHeight sẽ bị bỏ qua nếu nhỏ hơn
minHeight hoặc nếu tính năng đổi kích thước theo chiều dọc không được bật.
Ra mắt trong Android 12. |
resizeMode |
Chỉ định các quy tắc mà theo đó có thể đổi kích thước tiện ích. Bạn có thể sử dụng thuộc tính này để cho phép đổ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 thị các điểm điều khiển đổi kích thước,
sau đó kéo các điểm điều khiển theo chiều ngang hoặc chiều 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 kích thước tiện ích, hãy giả sử các thông số kỹ thuật sau:
- Một ô trong lưới có chiều rộng 30 dp và chiều cao 50 dp.
- Thông số kỹ thuật sau đây về 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 các 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ể đổi kích thước tiện ích xuống còn 2x1 hoặc lên đế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.
Chiều 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ể đổi kích thước tiện ích xuống còn 2x1 hoặc lên đến toàn màn hình.
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 đặc điểm khác ngoài kích thướ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 càng ít càng tốt
(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 |
Trỏ đế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 Hoạt động định cấu hình tiện ích trên trang này. |
description |
Chỉ định nội dung mô tả để 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ã khung hiển thị của khung hiển thị phụ của tiện ích được máy chủ của tiện ích tự động chuyển sang. |
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ỉ có home_screen là hợp lệ. |
widgetFeatures |
Khai báo các tính năng được tiện ích hỗ trợ. Ví dụ: nếu cấu hình của tiện ích 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 để kết xuất 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ể trong
glanceAppWidgettrênGlanceAppWidgetReceiver:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { // Let MyAppWidgetReceiver know which GlanceAppWidget to use override val glanceAppWidget: GlanceAppWidget = MyAppWidget() }
Bây giờ, bạn đã định cấu hình AppWidget bằng Glance.
Sử dụng lớp GlanceAppWidgetReceiver để xử lý các lượt truyền tin của tiện ích
GlanceAppWidgetReceiver điều phối các lượt truyền tin của tiện ích và các bản cập nhật trạng thái nền tảng
bằng cách mở rộng AppWidgetProvider cơ bản. Lớp này 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 các sự kiện đó thành các yêu cầu về vòng đời của Compose.
Khai báo tiện ích trong tệp kê khai
Khai báo lớp con GlanceAppWidgetReceiver làm một 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 receiver. Receiver phải chấp nhận hành động 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 của bạn (@xml/my_app_widget_info).
Triển khai lớp GlanceAppWidgetReceiver
Trong Glance, bạn sẽ mở rộng GlanceAppWidgetReceiver thay vì AppWidgetProvider trực tiếp. Triển khai bằng cách liên kết receiver với thực thể 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 bạn ghi đèonUpdatetheo cách thủ công, bạn phải gọisuper.onUpdateđể cho phép Glance chạy các luồng thành phần 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. Glance đọc các mục trong gói tuỳ chọn ở chế độ nền để bố cục của bạn điều chỉnh liền mạch dựa trên kích thước thời gian chạy.onDeleted(Context, IntArray): Được gọi bất cứ khi nào người dùng xoá một thực thể tiện ích cụ thể.onEnabled(Context): Được kích hoạt khi thực thể đầu tiên của tiện ích được tạo thành công. Tuyệt vời để chạy các hoạt động di chuyển toàn cầu.onDisabled(Context): Được gọi khi thực thể hoạt động cuối cùng của nhà cung cấp bị xoá.onReceive(Context, Intent): Chặn mọi lượt 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 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 một cách không đồng bộ.
Nhận ý định truyền tin của tiện ích
Ở chế độ nền, 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ước đó thực hiện những việc sau:
- Ở cấp cao nhất
Column, các mục được đặt theo chiều dọc lần lượt. Columnmở rộng kích thước để khớp với không gian có sẵn (thông quaGlanceModifiervà căn chỉnh nội dung của cột đó lên trên (verticalAlignment) và căn giữa theo chiều ngang (horizontalAlignment).- Nội dung của
Columnđược xác định bằng cách sử dụng lambda. Thứ tự rất quan trọng.- Mục đầu tiên trong
Columnlà thành phầnTextcó phần đệm12.dp. - Mục thứ hai là
Row, trong đó các mục được đặt theo chiều ngang lần lượt, với 2Buttonsđược căn giữa theo chiều ngang (horizontalAlignment). Màn hình cuối cùng phụ thuộc vào không gian có sẵn. Hình ảnh sau đây là ví dụ về giao diện có thể có:
- 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 nhau (chẳng hạn như phần đệ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à đối tượng 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 tiện ích cho ứ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 kích thước bán kính góc một cách linh hoạt 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 phương án dự phòng về tài nguyên chủ đề 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>