1. 事前準備
本程式碼實驗室會逐步引導您為 SociaLite 建立應用程式小工具。首先,您將建構簡易的「資訊一覽」小工具,並將其加入 SociaLite 及主畫面。接著,您將使用「資訊一覽」元件和主題為小工具加入零狀態。然後,本程式碼實驗室會逐步引導您支援使用者互動,讓使用者能從小工具中選取常用聯絡人。最後,您將學習如何從應用程式更新小工具。
必備條件
- 具備 Kotlin 基本知識。
- 完成「設定 Android Studio」程式碼實驗室,或熟悉 Android Studio 使用方式,且能在 Android 15 模擬器或搭載 Android 15 的實體裝置上測試應用程式。
- 具備 Hilt 基本知識。
- 具備 Compose 基本知識。雖然「資訊一覽」並不使用 Jetpack Compose 的可組合函式,但會重複使用框架和程式設計樣式。
本程式碼研究室涵蓋內容
- 如何設定應用程式以支援小工具。
- 如何使用「資訊一覽」元件建構回應式版面配置。
- 如何使用
GlanceTheme
在使用者的主畫面支援動態顏色。 - 如何在小工具中處理使用者互動。
- 如何從應用程式更新小工具。
需求條件
- 最新版 Android Studio。
- 搭載 Android 12 以上版本的測試裝置或模擬器。
- Android 12 以上版本的 SDK。
2. 做好準備
取得範例程式碼
- 如果您已完成「因應 Android 15 強制採用的無邊框措施」或「新增預測返回動畫」程式碼實驗室,則您已擁有範例程式碼,請跳到「新增小工具」部分。
- 前往 GitHub 下載範例程式碼。
或者,您也可以複製存放區,並查看 codelab_improve_android_experience_2024 分支。
git clone git@github.com:android/socialite.git
cd socialite
git checkout codelab_improve_android_experience_2024
- 在 Android Studio 中開啟 SociaLite,然後在 Android 15 裝置或模擬器上執行該應用程式。您會看到像是下方圖片的畫面:
採用手勢操作模式的 SociaLite
3. 新增小工具
什麼是小工具?
小工具是應用程式的一部分,可嵌入其他 Android 應用程式。最常見的小工具就是使用者的主畫面。
為應用程式加入小工具,可以讓使用者快速啟動常見任務、一眼掌握豐富資訊,以及使用您的內容自訂裝置。
什麼是「資訊一覽」?
Jetpack「資訊一覽」是一個使用 Kotlin 編寫小工具的程式庫,所用的 API 類似 Compose。「資訊一覽」與 Compose 具備幾個相同優點,例如可重新組合,能用 Kotlin 以宣告方式編寫 UI 程式碼,以及具有結構明確的元件。「資訊一覽」也減少了編寫小工具時使用 XML 遠端檢視的需求。
建立小工具
Android 上的小工具會在 AndroidManifest
中宣告為 <receiver>
元素。這個接收器應匯出,處理 android.appwidget.action.APPWIDGET_UPDATE
動作意圖,並透過 android.appwidget.provider
中繼資料元素提供應用程式小工具設定檔。
將小工具加入 SociaLite
您想在 SociaLite 中加入小工具,讓使用者看到自己的常用聯絡人,以及是否有他們的未讀訊息。如有未讀訊息,使用者輕觸小工具後,系統應開啟與相應常用聯絡人的即時通訊。此外,您會使用「資訊一覽」元件和主題設定,透過回應式設計與動態顏色,確保小工具呈現最佳效果。
首先,您要將靜態的「Hello World」小工具加入 SociaLite。之後,您可以擴充小工具的功能。
為達成這個目標,您需要執行以下操作:
- 將「資訊一覽」的依附元件加入應用程式。
- 建立
GlanceAppWidget
實作項目。 - 建立
GlanceAppWidgetReceiver
。 - 使用應用程式小工具資訊 XML 檔案來設定小工具。
- 將接收器和應用程式小工具資訊加入
AndroidManifest.xml
檔案。
將「資訊一覽」加入專案
範例程式碼已將「資訊一覽」的版本和程式庫座標加入 SociaLite 的版本目錄:libs.versions.toml
。
libs.versions.toml
[versions]
//..
glance = "1.1.0-beta02"
[libraries]
glance-appwidget = { group = "androidx.glance", name = "glance-appwidget", version.ref = "glance" }
glance-material = { group = "androidx.glance", name = "glance-material3", version.ref = "glance" }
此外,「資訊一覽」的依附元件也已包含在 SociaLite 的 app/build.gradle.kts
檔案中。
build.gradle.kts
dependencies {
...
implementation(libs.glance.appwidget)
implementation(libs.glance.material)
...
}
- 如您已修改這些檔案,請同步專案以下載「資訊一覽」程式庫。
建立 GlanceAppWidget
與 GlanceAppWidgetReceiver
Android 會透過廣播接收器來通知 SociaLite 某個小工具已新增、需要更新或已移除。「資訊一覽」提供一個抽象的接收器類別 GlanceAppWidgetReceiver,該類別可擴充 AppWidgetProvider。
GlanceAppWidgetReceiver
實作項目也負責提供 GlanceAppWidget
的例項。這個類別會將「資訊一覽」的可組合函式算繪成遠端檢視。
範例程式碼包含兩個類別:SocialiteAppWidget
(用以擴充 GlanceAppWidget
) 及 SocialiteAppWidgetReceiver
(用以擴充 GlanceAppWidgetReceiver
)。
如要開始,請按照下列步驟操作:
- 前往
app/src/main/java/com/google/android/samples/socialite/
找到widget
套件。 - 開啟
SociaLiteAppWidget
類別。此類別會覆寫provideGlance
方法。 - 使用呼叫
provideContent
取代TODO
,然後以參數形式傳遞小工具的可組合函式。目前這個小工具僅會顯示Hello World
訊息,但您會在本程式碼實驗室的後續部分中學習如何加入更多功能。
package com.google.android.samples.socialite.widget
import android.content.Context
import androidx.glance.GlanceId
import androidx.glance.GlanceTheme
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.provideContent
import androidx.glance.text.Text
class SociaLiteAppWidget : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {
provideContent {
GlanceTheme {
Text("Hello World")
}
}
}
}
- 接著,開啟
widget
套件中的SociaLiteAppWidgetReceiver
類別。您的接收器目前會提供一個SociaLiteWidget
的例項,但您會在接下來的章節中學習如何加入更多功能。 - 使用
SociaLiteAppWidget()
建構函式取代TODO
:
package com.google.android.samples.socialite.widget
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver
class SociaLiteAppWidgetReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = SociaLiteAppWidget()
}
現在您已準備好設定 Android 來顯示您的小工具,並允許使用者將其新增至主畫面。
新增應用程式小工具供應商資訊
- 在 res/xml 上按一下滑鼠右鍵,然後依序點選「New」(新增) >「XML resource file」(XML 資源檔案)。
- 輸入 socialite_widget_info 做為檔案名稱,appwidget-provider 做為根元素,然後按一下「OK」(確定)。這個檔案包含
AppWidgetHost
用來初始顯示小工具的appwidget
所需的中繼資料。 - 在 socialite_widget_info.xml 檔案中加入以下程式碼:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="3600000"
android:minHeight="128dp"
android:minWidth="128dp"
android:minResizeHeight="128dp"
android:minResizeWidth="128dp"
android:configure="com.google.android.samples.socialite.widget.SociaLiteAppWidgetConfigActivity"
android:widgetFeatures="configuration_optional|reconfigurable"
android:previewImage="@drawable/widget_preview"
android:maxResizeHeight="512dp"
android:maxResizeWidth="512dp"
android:targetCellWidth="2"
android:targetCellHeight="2"
android:initialLayout="@layout/glance_default_loading_layout">
</appwidget-provider>
下表概略說明此程式碼中的每個屬性:
屬性名稱 | 說明 |
| 系統可能會調整小工具的垂直和水平大小。 |
| 指定小工具加入主畫面時的預設大小。 |
| 控制小工具主機何時會重新整理小工具。只要您的應用程式正在執行且有新資訊可供顯示,就可以更新小工具。 |
| 設定小工具可調整的最小尺寸。 |
| 指定小工具加至主畫面時的最小預設尺寸。 |
| 在「資訊一覽」算繪可組合函式時,顯示初始版面配置。 |
| 提供會顯示在小工具挑選器中的小工具靜態圖像。 |
| 指示小工具支援的各種功能。這些內容是給小工具主機的提示,實際上並不會改變小工具的行為。 |
| 設定活動類別的名稱。這個活動可在稍後設定小工具。 |
如要查看所有可用的屬性,包括 API 31 以上版本的功能,請參閱 AppWidgetProviderInfo
。
更新 AndroidManifest
並測試
最後,您已準備好更新 AndroidManifest.xml
檔案並測試小工具。請在檔案中將 receiver
元素定義為 application
元素的子項。這個接收器會處理 APPWIDGET_UPDATE
意圖,並將 appwidget
中繼資料提供給 Android 啟動器。
如要開始,請按照下列步驟操作:
- 為
SociaLiteAppWidgetReceiver
建立receiver
元素,以供匯出。複製下列程式碼並貼到AndroidManifest.xml
檔案中application
元素之後:
<receiver
android:name=".widget.SociaLiteAppWidgetReceiver"
android:exported="true"
android:label="Favorite Contact">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/socialite_widget_info" />
</receiver>
- 編譯並執行應用程式。
- 應用程式執行後,將小工具新增到主畫面。例如,在 Pixel 上,長按背景,選取「Widgets」(小工具) >「SociaLite」。您應該可以將小工具新增到主畫面。
背景透明的小工具顯示「Hello World」。不可否認,這個小工具目前外觀簡陋,功能也有限。在下一節中,您會為小工具加入更複雜的版面配置,並使用 Material Design 的繽紛色彩美化外觀。
4. 改善設計
目前的小工具僅具靜態功能,缺乏實用小工具應具備的許多特徵。一個實用的小工具應該:
- 展示簡潔的最新內容,並提供簡單易用的功能。
- 能夠調整版面配置,盡量減少突兀的空隙。
- 套用應用程式小工具主機背景的顏色。
如要深入瞭解何謂實用的小工具,請參閱小工具。
新增 Scaffold
現在您要更新小工具,以顯示在「資訊一覽」Scaffold
元件中。
Scaffold
由「資訊一覽」程式庫提供,這個簡單的 Slot API 可顯示具有 TitleBar
的小工具使用者介面。這個介面會將背景顏色設定為 GlanceTheme.colors.widgetBackground
,並套用邊框間距,是設計小工具時的頂層元件。
如要開始,請按照下列步驟操作:
- 使用下列程式碼取代
SociaLiteAppWidget
的實作項目:
package com.google.android.samples.socialite.widget
import android.content.Context
import androidx.compose.runtime.Composable
import androidx.glance.GlanceId
import androidx.glance.GlanceModifier
import androidx.glance.GlanceTheme
import androidx.glance.ImageProvider
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.components.Scaffold
import androidx.glance.appwidget.components.TitleBar
import androidx.glance.appwidget.provideContent
import androidx.glance.layout.fillMaxSize
import androidx.glance.text.Text
import com.google.android.samples.socialite.R
class SociaLiteAppWidget : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {
provideContent {
GlanceTheme() {
Content()
}
}
}
@Composable
private fun Content() {
Scaffold(titleBar = {TitleBar(startIcon = ImageProvider(R.drawable.ic_launcher_monochrome), title = "SociaLite")},
modifier = GlanceModifier.fillMaxSize()) {
Text("Hello World")
}
}
}
- 如要查看更新,請重新執行應用程式,然後將小工具的新副本新增到主畫面。
請記住,小工具是由外部主機顯示的遠端檢視。稍後,您會學習如何新增功能,以在應用程式內部自動更新小工具。在那之前,您必須從小工具挑選器新增小工具,才能看到程式碼的變更。
如您所見,小工具的呈現效果已比之前要好,但與其他小工具相比,顏色似乎不太合適。在主畫面中,小工具的顏色應該配合使用者的主題設定。使用動態顏色符記,您就可以讓小工具的主題配合裝置的桌布和主題。
加入動態顏色
現在,請將 widgetBackground
顏色符記加入到 Scaffold 背景,並將 onSurface
顏色符記加入 TitleBar
文字及 Text 元件。如要更新文字樣式,請匯入 TextStyle
「資訊一覽」類別。如要更新 Scaffold 背景,請將 Scaffold
的 backgroundColor
屬性設定為 GlanceTheme.colors.widgetBackground
。
如要開始,請按照下列步驟操作:
- 在 SociaLiteAppWidget.kt 檔案中引入新的匯入內容。
//Add to the imports section of your Kotlin code.
import androidx.glance.text.TextStyle
- 更新
Content
可組合函式以新增widgetBackground
。
Scaffold(
titleBar = {
TitleBar(
textColor = GlanceTheme.colors.onSurface,
startIcon = ImageProvider(R.drawable.ic_launcher_monochrome),
title = "SociaLite",
)
},
backgroundColor = GlanceTheme.colors.widgetBackground,
modifier = GlanceModifier.fillMaxSize(),
) {
Text(text = "Hello World", style = TextStyle(color = GlanceTheme.colors.onSurface))
}
- 如要查看更新,請重新執行應用程式,並將小工具的新副本新增到主畫面。
現在,小工具與主畫面上其他小工具的主題會保持一致;若您變更背景或設定深色模式,小工具會自動更新顏色。若使用五彩繽紛的背景,小工具會根據所處區域的顏色自動調整外觀。
|
|
新增零狀態
現在您需要考慮狀態和小工具的設定。小工具新增到主畫面後,但尚未完成設定時,通常最好顯示零狀態。這種狀態可提示使用者設定小工具。您需要為小工具加入設定活動,並從零狀態連結至該活動。
本程式碼實驗室提供用來儲存、存取和修改小工具設定狀態的類別。您將學習如何新增程式碼以更新小工具 UI 來顯示此狀態,並建立 lambda 動作來處理使用者的輕觸動作。
檢查小工具模型
請花點時間查看 com.google.android.samples.socialite.widget.model
套件中的類別。
其中包含 WidgetModel
、WidgetModelDao
與 WidgetModelRepository
類別。這些類別已包含在本程式碼實驗室的範例程式碼中,並處理將小工具狀態保存到底層 Room
資料庫的問題。此外,這些類別使用 Hilt 來管理生命週期。
WidgetModel
類別包含一個由 Android 指派的 widgetId
、所顯示的 SociaLite 聯絡人的 contactId
、要顯示的 displayName
與 photo
,以及一個布林值 (表示是否有來自聯絡人的未讀訊息)。SociaLiteAppWidget
可組合函式會取用這些內容,並顯示在小工具中。
WidgetModelDao
是資料存取物件,可簡化對 SociaLite 資料庫的存取權。WidgetModelRepository
則提供建立、讀取、更新及刪除 WidgetModel
例項的便利函式。這些類別由 Hilt 建立,並透過依附元件插入功能插入應用程式。
- 前往
app/src/main/java/com/google/android/samples/socialite/widget/model/
,開啟model
套件中的WidgetModel.kt
檔案。
這是一個使用 Entity
註解的 data
類別。Android 會為每個小工具例項指派一個專屬的 ID,而 SociaLite 會將這個 ID 用做模型資料的主鍵。模型的每個例項都會追蹤關聯聯絡人的基本資訊,以及是否有來自聯絡人的未讀訊息。
@Entity(
foreignKeys = [
ForeignKey(
entity = Contact::class,
parentColumns = ["id"],
childColumns = ["contactId"],
onDelete = ForeignKey.CASCADE,
),
],
indices = [
Index("widgetId"),
Index("contactId"),
],
)
data class WidgetModel(
@PrimaryKey val widgetId: Int,
val contactId: Long,
val displayName: String,
val photo: String,
val unreadMessages: Boolean = false,
) : WidgetState
零狀態
您想讓 Content
可組合函式從 WidgetModelRepository
載入小工具的模型。若沒有可用的模型,就顯示零狀態;否則顯示小工具的一般內容。目前,一般內容為「Hello World」訊息,但在下一章節,您會建立更出色的介面。
您將使用 when
運算式取代 Content
可組合函式,根據是否有可用模型,顯示 ZeroState
可組合函式或 Text
預留位置。
- 在
provideGlance
方法中,於可組合函式之外,取得WidgetModelRepository
和目前小工具 ID 的參照。在SociaLiteAppWidget
provideGlance
方法的provideContent
之前新增以下行。
override suspend fun provideGlance(context: Context, id: GlanceId) {
val widgetId = GlanceAppWidgetManager(context).getAppWidgetId(id)
val repository = WidgetModelRepository.get(context)
您也可能需要新增以下匯入項目:
import com.google.android.samples.socialite.widget.model.WidgetModel
import com.google.android.samples.socialite.widget.model.WidgetModelRepository
import com.google.android.samples.socialite.widget.model.WidgetState.Loading
import androidx.glance.appwidget.GlanceAppWidgetManager
- 將存放區和小工具 ID 以參數形式加入
Content
可組合函式,然後用以載入模型。更新Content
可組合函式的簽章,並新增以下行:
private fun Content(repository: WidgetModelRepository, widgetId: Int) {
val model = repository.loadModel(widgetId).collectAsState(Loading).value
- 若 Android Studio 沒有自動新增以下匯入項目,請手動新增。
import androidx.compose.runtime.collectAsState
此外,您也需要更新 provideGlance
,將小工具 ID 和存放區傳遞給 Content
。
請使用以下內容取代 provideGlance
:
override suspend fun provideGlance(context: Context, id: GlanceId) {
val widgetId = GlanceAppWidgetManager(context).getAppWidgetId(id)
val repository = WidgetModelRepository.get(context)
provideContent {
GlanceTheme {
Content(repository, widgetId)
}
}
}
- 在
Content
可組合函式中,根據模型是否存在來決定要顯示的狀態。使用這個 when 區塊取代Scaffold
元件及其內容,將Scaffold
與小工具內容移到ZeroState
可組合函式中:
when (model) {
is WidgetModel -> {Text("Hello World")}
else -> ZeroState(widgetId)
}
ZeroState
可組合函式已包含在 com.google.android.samples.socialite.widget.ui
套件內的範例程式碼中。
- 若 Android Studio 沒有自動匯入
com.google.android.samples.socialite.widget.ui
套件,請在SociaLiteAppWidget
的匯入部分新增下列程式碼。
import com.google.android.samples.socialite.widget.ui.ZeroState
- 如要查看更新,請重新執行應用程式,並將小工具的新副本新增到主畫面。您會看到小工具顯示 ZeroState 元件和一個按鈕。按一下按鈕會開啟設定活動。在下一節中,您將透過這個活動更新小工具的狀態。
設定活動
檢視 ZeroState 可組合函式。這個函式可在 ZeroState.kt
檔案的 com.google.android.samples.socialite.widget.ui
套件中找到。
@Composable fun ZeroState(widgetId: Int) { val widgetIdKey = ActionParameters.Key<Int>(AppWidgetManager.EXTRA_APPWIDGET_ID) Scaffold( titleBar = { TitleBar( modifier = GlanceModifier.clickable(actionStartActivity(MainActivity::class.java)), textColor = GlanceTheme.colors.onSurface, startIcon = ImageProvider(R.drawable.ic_launcher_monochrome), title = "SociaLite", ) }, backgroundColor = GlanceTheme.colors.widgetBackground, modifier = GlanceModifier.fillMaxSize(), ) { Box(modifier = GlanceModifier.fillMaxSize(), contentAlignment = Alignment.Center) { Button( text = "Select Favorite Contact", onClick = actionStartActivity<SociaLiteAppWidgetConfigActivity>( parameters = actionParametersOf(widgetIdKey to widgetId), ), ) } } }
Scaffold
可組合函式已移入 ZeroState
可組合函式。TitleBar
具有 clickable
修飾符,可開啟 SociaLite 的主要活動。ZeroState
使用「資訊一覽」Button
可組合函式向使用者顯示行動號召,按一下後會開啟 SociaLiteAppWidgetConfigActivity
活動,並以意圖額外項目形式加入小工具 ID。這兩個動作都使用「資訊一覽」的 actionStartActivity
便利函式。如要進一步瞭解動作,請參閱處理使用者互動。
- 檢視
SociaLiteAppWidgetConfigActivity
如何用來更新小工具的設定。這個類別也是小工具的設定活動。設定活動會讀取具有AppWidgetManager.
*EXTRA_APPWIDGET_ID.
* 索引鍵的整數意圖額外項目。如要進一步瞭解設定活動,請參閱協助使用者設定應用程式小工具。 - 在
SociaLiteAppWidgetConfigActivity
中,請使用以下程式碼取代ContactRow
onClick
屬性中的TODO
:
{
coroutineScope.launch {
widgetModelRepository.createOrUpdate(
WidgetModel(
appWidgetId,
contact.id,
contact.name,
contact.iconUri.toString(),
false,
),
)
SociaLiteAppWidget().updateAll(this@SociaLiteAppWidgetConfigActivity)
val resultValue = Intent().putExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
appWidgetId,
)
setResult(RESULT_OK, resultValue)
finish()
}
}
若 Android Studio 沒有自動新增以下包含內容,請新增相關內容:
import com.google.android.samples.socialite.widget.model.WidgetModel
import androidx.glance.appwidget.updateAll
import kotlinx.coroutines.launch
這個程式碼區塊會更新您的小工具狀態。首先,這個區塊會使用存放區來儲存或更新 WidgetModel
中所選聯絡人的資訊。接著,它會呼叫 updateAll
暫停函式。這個函式會更新主畫面上的所有小工具,您可以在應用程式的任何地方呼叫這個函式。最後,這個區塊會設定活動結果,指示已成功更新小工具。
- 執行並取代主畫面上的小工具。您應該會看到新的零狀態。
- 按一下「Select favorite contact」(選取常用聯絡人),系統會隨即帶您前往設定活動。
- 選取聯絡人。您的小工具會隨即更新。不過,小工具並未顯示您的常用聯絡人,而您將會在下一節加入此功能。
管理小工具資料
- 請開啟 App Inspection 工具,按需要連結至程序,然後選取「資料庫檢查器」分頁標籤,查看應用程式資料庫的內容。
- 在小工具中選取常用聯絡人,並確認其更新為「Hello World」。回到 App Inspection 工具,您應該會看到一個小工具條目出現在「Widget model」(小工具模型) 分頁標籤中。您可能需要重新整理表格或按「Live updates」(即時更新) 來查看變更。
- 新增其他小工具並選取其他聯絡人。您可能需要按「Refresh table」(重新整理表格) 或「Live updates」(即時更新) 才能看到新模型。
- 移除小工具,注意在移除小工具之後,模型仍會保留在資料庫中。
您可以透過覆寫 onDeleted
來更新 SociaLiteAppWidgetReceiver
,在移除小工具時清理資料庫。
如要清理孤立的小工具模型,可以呼叫 WidgetModelRepository.cleanupWidgetModels
。這個存放區類別由 Hilt 管理,因此您需要使用依附元件插入功能來取得例項。
- 在
SociaLiteAppWidgetReceiver
中,將AndroidEntryPoint
Hilt 註解加到接收器類別宣告中,並插入WidgetModelRepository
例項。 - 在方法中呼叫
WidgetModelRepository.cleanupWidgetModels
來覆寫onDeleted
。
您的程式碼應如下所示:
package com.google.android.samples.socialite.widget
import android.content.Context
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver
import com.google.android.samples.socialite.widget.model.WidgetModelRepository
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class SociaLiteAppWidgetReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = SociaLiteAppWidget()
@Inject
lateinit var repository: WidgetModelRepository
override fun onDeleted(context: Context, appWidgetIds: IntArray) {
super.onDeleted(context, appWidgetIds)
repository.cleanupWidgetModels(context)
}
}
- 重新執行應用程式。當您將小工具從主畫面中移除時,應該會看到模型行已從應用程式檢查器中移除。
5. 新增聯絡人使用者介面,並在收到新訊息時更新
您已進入本程式碼實驗室的最後一個步驟。在本節中,您將為小工具實作最終的聯絡人使用者介面,並在有未讀訊息時更新介面。
- 檢視模型套件中的
WidgetModelRepository
類別。
您會在這裡使用 updateUnreadMessagesForContact
便利方法;這種方法會更新與聯絡人 ID 相關聯的小工具。
//Don't add this code.
fun updateUnreadMessagesForContact(contactId: Long, unread: Boolean) {
coroutineScope.launch {
widgetModelDao.modelsForContact(contactId).filterNotNull().forEach { model ->
widgetModelDao.update(
WidgetModel(model.widgetId, model.contactId, model.displayName, model.photo, unread)
)
SociaLiteAppWidget().updateAll(appContext)
}
}
}
此方法有兩個參數:contactId
為正在更新的聯絡人 ID,unread
為布林值,表示未讀訊息狀態。此方法會使用 WidgetModelDao
,找出所有顯示這個聯絡人的小工具模型,並使用新的讀取狀態更新模型。接著,這個函式會呼叫「資訊一覽」提供的 SociaLiteAppWidget().updateAll
方法,更新使用者主畫面上的所有小工具。
現在您已瞭解小工具及其狀態的更新方式,接下來就可以建立聯絡人使用者介面、傳送訊息,並觀察更新過程。為此,您需要在小工具版面配置中使用 FavoriteContact
可組合函式更新 SociaLiteAppWidget
。在此版面配置中,您還需要檢查是否應顯示 No new messages
還是 New Messages!
。
- 檢視
com.google.android.samples.socialite.widget.ui
套件中的FavoriteContact.kt
檔案。
//Don't add this code.
@Composable
fun FavoriteContact(model: WidgetModel, onClick: Action) {
Column(
modifier = GlanceModifier.fillMaxSize().clickable(onClick)
.background(GlanceTheme.colors.widgetBackground).appWidgetBackground()
.padding(bottom = 8.dp),
verticalAlignment = Alignment.Vertical.Bottom,
horizontalAlignment = Alignment.Horizontal.CenterHorizontally,
) {
Image(
modifier = GlanceModifier.fillMaxWidth().wrapContentHeight().defaultWeight()
.cornerRadius(16.dp),
provider = ImageProvider(model.photo.toUri()),
contentScale = ContentScale.Crop,
contentDescription = model.displayName,
)
Column(
modifier = GlanceModifier.fillMaxWidth().wrapContentHeight().padding(top = 4.dp),
verticalAlignment = Alignment.Vertical.Bottom,
horizontalAlignment = Alignment.Horizontal.CenterHorizontally,
) {
Text(
text = model.displayName,
style = TextStyle(
fontWeight = FontWeight.Bold,
fontSize = 24.sp,
color = (GlanceTheme.colors.onSurface),
),
)
Text(
text = if (model.unreadMessages) "New Message!" else "No messages",
style = TextStyle(
fontWeight = FontWeight.Bold,
fontSize = 16.sp,
color = (GlanceTheme.colors.onSurface),
),
)
}
}
}
- 將
SociaLiteAppWidget
中Content
可組合函式的Text("Hello World")
替換為呼叫FavoriteContact
可組合函式。
這個可組合函式會接收 WidgetModel 和一個由 actionStartActivity
「資訊一覽」函式所建立的動作。
- 當模型並非
WidgetModel
時,請在ZeroState
之前加入對when
區塊的呼叫。
when (model) {
is WidgetModel -> FavoriteContact(model = model, onClick = actionStartActivity(
Intent(LocalContext.current.applicationContext, MainActivity::class.java)
.setAction(Intent.ACTION_VIEW)
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
.setData("https://socialite.google.com/chat/${model.contactId}".toUri()))
)
else -> ZeroState(widgetId)
}
- 若 Android Studio 沒有自動新增以下匯入項目,請現在新增:
import com.google.android.samples.socialite.widget.ui.FavoriteContact
import androidx.glance.appwidget.action.actionStartActivity
import android.content.Intent
import com.google.android.samples.socialite.MainActivity
import androidx.core.net.toUri
- 執行應用程式。
- 選擇一位常用聯絡人,傳送訊息,並在對方回覆之前立即結束應用程式。收到回覆訊息時,小工具的狀態應會改變。
- 按一下小工具開啟即時通訊,然後當您返回主畫面時,應會看到狀態再次更新。
6. 恭喜
您已經成功完成本程式碼實驗室,並學會如何使用「資訊一覽」編寫小工具!您應該能輕鬆地建立精緻的小工具,讓小工具在多種主畫面上呈現出色效果、處理使用者輸入內容,並能自行更新。
如要取得 main
分支的解決方案程式碼,請按照下列步驟操作:
- 如已下載 SociaLite,請執行以下指令:
git checkout main
- 否則,請再次下載程式碼以查看
main
分支:
git clone git@github.com:android/socialite.git