前言
Jetpack Glance 是基于 Jetpack Compose 运行时构建的框架,可以使用Compose API 开发和设计桌面小组件 widget。
正文
1.添加依赖
dependencies {
...
//添加依赖
implementation "androidx.glance:glance-appwidget:1.1.0"
implementation "androidx.glance:glance-material3:1.1.0"
}
2.清单文件中注册
<receiver android:name=".MyAppWidgetReceiver"
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>
3.添加Receiver文件
class MyAppWidgetReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget = MyAppWidget()
}
4.添加my_app_widget_info文件
在res/xml文件夹中创建my_app_widget_info文件,并配置
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="100dp"//最小宽度
android:minHeight="50dp"//最大宽度
android:updatePeriodMillis="1800000"//刷新间隔,最低半个小时
android:resizeMode="horizontal|vertical"
android:initialLayout="@layout/glance_default_loading_layout">//初始布局
</appwidget-provider>
5.创建widget,并用Compose写界面
可以看到,导的包和Jetpack Compose的包是不同的,这个包内的api非常少
据官方文档上所写,是因为要将其映射为原生的RemoteViews
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) {
provideContent {
GlanceTheme {
MyContent()
}
}
}
@Composable
private fun MyContent() {
Column(
modifier = GlanceModifier.fillMaxSize()
.background(GlanceTheme.colors.background),
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>()
)
}
}
}
}
6.ui中的一些问题
由于不能写阴影,因此使用了shape叠加的方式来实现类似的阴影效果(阴影层是半透明的,并且前景层加了一点偏移):
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 阴影层 -->
<item>
<shape android:shape="rectangle">
<solid android:color="#1B707070"/> <!-- 阴影颜色和透明度 -->
<corners android:radius="@dimen/dp4"/> <!-- 圆角半径 -->
</shape>
</item>
<!-- 前景层 -->
<item android:top="@dimen/dp0_5" android:left="@dimen/dp0_5" android:bottom="@dimen/dp1" android:right="@dimen/dp1">
<shape>
<solid android:color="@color/ps_color_white"/>
<corners android:radius="@dimen/dp4"/>
</shape>
</item>
</layer-list>
使用Modifier或给Image设置图片:
Image(ImageProvider(R.drawable.widget_no_data), null)
给控件设置点击跳转到Activity:
Button(
text = "Home",
onClick = actionStartActivity<MyActivity>()
)
或
GlanceModifier.clickable(actionStartActivity<MyActivity>())//注意这里用的是小括号,因为方法返回的是一个Action对象
7.刷新widget的ui
MyAppWidget().updateAll(context)//子线程中
ps:由于widget至少半小时才能刷新第二次,所以建议放在app回到桌面时在进行刷新,比如使用如下方式判断离开了app:
//Application中
registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {
activeCount++
}
override fun onActivityPaused(activity: Activity) {
activeCount--
if (activeCount <= 0) {
activeCount = 0
//app切换到了后台
}
}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {}
})
总结
方便,但只方便了一点
基本只支持几个compose的api,像阴影,圆角什么的都不支持(因此使用shape来实现)
参考: Jetpack Glance | Jetpack Compose | Android Developers
对Kotlin或KMP感兴趣的同学可以进Q群 101786950
如果这篇文章对您有帮助的话
可以扫码请我喝瓶饮料或咖啡(如果对什么比较感兴趣可以在备注里写出来)