iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0
Mobile Development

【Kotlin Notes And JetPack】Build an App系列 第 25

Day 25.【UI】App Widget 新體驗

  • 分享至 

  • xImage
  •  

今天要來玩玩新的 library Glance,因為還在 alpha 階段,所以建議大家先體驗看看就好,以下如有解釋不清或是描述錯誤的地方還請大家多多指教:

什麼?

Glance 這套 library 主要是強調以更快更簡單的方式來建立 app widget,他是以 jetpack compose 為基底的介面操作,所以在開發的時候要設置 compose,轉譯成 RemoteView 最終呈現在畫面上,以下列了幾個 Android 12 以後才出現的設置:

  • appwidget-provider : targetCellWidth/targetCellHeight (設置 default 格數占比)
    12 以下則繼續使用 minHeight/minWidth (dp)
  • appwidget-provider : MaxResizeWidth/MaxResizeHeight, MinResizeWidth/MinResizeHeight (限制可 resize 的最大及最小範圍 - dp)
  • appwidget-provider : description (什麼功能的 widget 敘述)
  • appwidget-provider : previewLayout (在選擇器上呈現的 preview)
    12 以前透過 previewImage 來設置靜態的圖示,previewLayout 可以精準的呈現資料

如何?

| Set up

設置 dependency 及 enable Compose

dependencies {
    // For AppWidgets support
    implementation "androidx.glance:glance-appwidget:1.0.0-alpha05"
}

android {
    buildFeatures {
        compose true
    }

    composeOptions {
        kotlinCompilerExtensionVersion = "1.2.0-beta01" 
    }

    kotlinOptions {
        jvmTarget = "1.8" // 這裡我使用 11
    }
}

這邊要注意的地方是,compose 有對應的 kotlin 版本,針對自己所運行的版本去設置 compose 版號,請參考這份

| 設置 Widget

建立 widget 設定要呈現的 style

class WeatherWidget : GlanceAppWidget() {
    @Composable
    override fun Content() {
        Column(modifier = GlanceModifier.padding(all = 16.dp)) {
            val prefs = currentState<Preferences>()
            val checkWarn = prefs[booleanPreferencesKey("uva_warn")] ?: false
            Row(modifier = GlanceModifier.padding(16.dp)) {
                Text(text = "UVA")
                Switch(checked = checkWarn, onCheckedChange = actionRunCallback<SwitchAction>())
            }
        }
    }
}

設置 switch 的 action 行為

class SwitchAction : ActionCallback {
    override suspend fun onAction(
        context: Context,
        glanceId: GlanceId,
        parameters: ActionParameters
    ) {
        updateAppWidgetState(context, PreferencesGlanceStateDefinition, glanceId) {
            it.toMutablePreferences()
                .apply {
                    val checkWarn = this[booleanPreferencesKey("uva_warn")] ?: false
                    this[booleanPreferencesKey("uva_warn")] = !checkWarn
                }
        }
        WeatherWidget().update(context, glanceId)
    }
}

| AppWidgetProvider

設置 AppWidgetProvider,在 Glance 中叫做 GlanceAppWidgetReceiver(),他繼承了原本的 AppWidgetProvider:

class WeatherWidgetProvider: GlanceAppWidgetReceiver() {
    override val glanceAppWidget: GlanceAppWidget = WeatherWidget()
}

| 建置 provider xml

在 resourece 建立 appwidget-provider

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
        android:minWidth="250dp"
        android:minHeight="40dp"
        android:resizeMode="horizontal|vertical"
        android:updatePeriodMillis="86400000"
        android:widgetCategory="home_screen">
</appwidget-provider>

| 註冊 Reciever

GlanceAppWidgetReceiver 是一個 BroadcastReceiver,所以要在 Manifest 註冊 (與舊有的方式依樣)

<receiver
        android:name=".widget.WeatherWidgetProvider"
        android:exported="true"
        android:label="天氣預告">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>

    <meta-data
         android:name="android.appwidget.provider"
         android:resource="@xml/weather_widget_info" />
</receiver>

運行之後就可以看見帶有 switch 的 widget 了

Reference

AppWidget Sample


上一篇
Day 24.【Architecture】LiveData 的介紹與應用
下一篇
Day 26.【DI】Hilt 的介紹與應用
系列文
【Kotlin Notes And JetPack】Build an App30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言