Jetpack Compose 中的 Glance 是一个用于构建 App Widgets 的新框架。Glance 利用 Jetpack Compose 的声明式 UI 模型和 Kotlin 的现代语言特性来简化 Widget 的创建和管理。
Glance 简介
Glance 提供了一种使用 Compose 风格的方式来构建 App Widgets,支持自定义 UI 组件、事件处理和状态管理。与传统的 RemoteViews 不同,Glance 允许开发者使用 Compose 的声明式编程模型,使得创建复杂和动态的 Widgets 更加容易和灵活。
关键组件
- GlanceAppWidget:这是创建 Widget 的入口点。
- GlanceAppWidgetReceiver:用于接收 App Widget 更新的广播接收器。
- GlanceStateDefinition:定义如何保存和恢复 Widget 的状态。
- GlanceComposable:用于定义 Widget UI 的可组合函数。
示例代码
下面是一个简单的 Glance 示例,它显示了一个带有按钮和文本的 Widget,当按钮被点击时,文本内容会发生变化。
1. 添加依赖项
首先,在项目的 build.gradle 文件中添加 Glance 依赖项:
dependencies {
implementation "androidx.glance:glance:<version>"
}
请确保将 <version> 替换为最新的 Glance 库版本。
2. 创建 GlanceAppWidget
创建一个新的 Kotlin 文件,定义一个继承自 GlanceAppWidget 的类。
import android.content.Context
import androidx.compose.runtime.Composable
import androidx.glance.GlanceAppWidget
import androidx.glance.GlanceAppWidgetReceiver
import androidx.glance.GlanceId
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver
import androidx.glance.appwidget.state.updateAppWidgetState
import androidx.glance.appwidget.updateAll
import androidx.glance.layout.*
import androidx.glance.state.GlanceStateDefinition
import androidx.glance.state.PreferencesGlanceStateDefinition
import androidx.glance.text.Text
import androidx.glance.unit.ColorProvider
import androidx.glance.unit.dp
class MyGlanceAppWidget : GlanceAppWidget() {
@Composable
override fun Content() {
MyWidgetContent()
}
}
@Composable
fun MyWidgetContent() {
val context = LocalContext.current
// 获取当前状态
val state = currentState<MyWidgetState>() ?: MyWidgetState()
// 定义 UI
Column(
modifier = GlanceModifier
.fillMaxSize()
.padding(16.dp)
) {
Text(
text = state.text,
style = TextStyle(color = ColorProvider(Color.Black)),
modifier = GlanceModifier.padding(bottom = 8.dp)
)
Button(
text = "Click Me",
onClick = actionRunCallback<MyWidgetAction>()
)
}
}
data class MyWidgetState(
val text: String = "Hello, Glance!"
)
class MyWidgetAction : ActionCallback {
override suspend fun onRun(context: Context, glanceId: GlanceId) {
// 更新状态
updateAppWidgetState(context, glanceId) { state ->
state.toMutablePreferences().apply {
val currentText = this[PreferencesKeys.Text] ?: "Hello, Glance!"
this[PreferencesKeys.Text] = if (currentText == "Hello, Glance!") "Clicked!" else "Hello, Glance!"
}
}
MyGlanceAppWidget().update(context, glanceId)
}
}
object PreferencesKeys {
val Text = preferencesKey<String>("text")
}
class MyGlanceAppWidgetReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = MyGlanceAppWidget()
}
3. 注册 GlanceAppWidgetReceiver
在 AndroidManifest.xml 中注册 GlanceAppWidgetReceiver:
<receiver
android:name=".MyGlanceAppWidgetReceiver"
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/glance_widget_info"/>
</receiver>
在 res/xml 目录下创建 glance_widget_info.xml 文件,定义 Widget 的配置信息:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/initial_widget_layout"
android:minWidth="180dp"
android:minHeight="110dp"
android:updatePeriodMillis="86400000"
android:previewImage="@drawable/preview"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen">
</appwidget-provider>
4. 创建 Widget 的初始布局
在 res/layout 目录下创建一个 initial_widget_layout.xml 文件,用于定义 Widget 的初始布局:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"/>
总结
以上示例展示了如何使用 Jetpack Compose 中的 Glance 来创建一个简单的 App Widget。通过定义 GlanceAppWidget、GlanceAppWidgetReceiver、GlanceStateDefinition 和 GlanceComposable,可以轻松地构建和管理复杂的 Widget UI。Glance 提供了一个现代的、声明式的方式来处理 Widgets,使得开发过程更加直观和高效。