作者:HyejeanMOON 转载地址:https://juejin.cn/post/7098975953199726606
因为在iOS14中推出的小组件的功能,让大家重新开始关注起小组件了。虽然安卓是很久之前就有了小组件的功能,但是因为它的不美观和不实用,以及对开发者也不够友好,逐渐变成为废弃的状态。
直到Android12,再一次更新了小组件的的相关功能,并且为了减少开发者的负担而推出了Jetpack Glance库。该库是基于Compose,是开发者利用Compose的命令快速上手进而减少开发成本。
那让我们开始探究一下Glance吧。
1. 加上库的依赖
把下面的依赖信息添加到app的build.gralde文件中。
dependencies {
? ? implementation("androidx.glance:glance:1.0.0-alpha01")
}
android {
? ? buildFeatures {
? ? ? ? compose = true
? ? }
? ? composeOptions {
? ? ? ? kotlinCompilerExtensionVersion = "1.1.0-beta03"
? ? }
? ? kotlinOptions {
? ? ? ? jvmTarget = "1.8"
? ? }
}
2. 继承GlanceAppWidget类
我们需要继承GlanceAppWidget类然后重写Content方法。
class GlanceWidget : GlanceAppWidget(){
@Composable
override fun Content() {
// write compose ui code here
}
}
在Content方法内写我们已经很熟悉的Compose UI语句就可以了。
但是这里有一点需要格外的注意。我们在使用Compose UI组件时需要使用glance的提供UI组件。 而不是Compose Material的UI组件。
组件的具体路径如下:(以Text为举例) Glance提供的Compose UI组件: androidx.glance.text.Text Compose Material提供的Compose UI组件:androidx.compose.material.Text
Glance提供的所有Compose UI组件列表如下:
Box, Column, Row, Text, Image, Button, LazyColumn, Spacer.
简单说明一下,为什么这里需要使用的是Glance提供的组件而不是Compose Material的。
因为Glance的底层还是通过构建RemoteViews来实现小组件的显示。所以我们只能利用Glance提供的UI组件,然后让Glance帮我们把写好的UI代码转换成RemoveViews。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gs98xMk9-1652882520252)(https://upload-images.jianshu.io/upload_images/28055051-26e8ba036c350d0d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
不光是需要使用Glance提供的Compose UI组件,为ui组件设置modifier的时候我们也不能使用普通的modifier,而是需要使用Glance提供的GlanceModifier。
3. 小组件布局的自适应
利用Glance,我们可以为小组件设置不同大小的布局来实现用户在自由的调节组件大小时显示不同的界面。
为了实现小组件布局的自适应,我们首先要设置具体的布局大小。我们要重写sizeMode变量,在这里规定小组件都有哪些大小的布局。
private val SMALL_BOX = DpSize(90.dp, 90.dp)
private val BIG_BOX = DpSize(180.dp, 180.dp)
private val VERY_BIG_BOX = DpSize(300.dp, 300.dp)
private val ROW = DpSize(180.dp, 48.dp)
private val LARGE_ROW = DpSize(300.dp, 48.dp)
private val COLUMN = DpSize(48.dp, 180.dp)
private val LARGE_COLUMN = DpSize(48.dp, 300.dp)
override val sizeMode = SizeMode.Responsive(
setOf(SMALL_BOX, BIG_BOX, ROW, LARGE_ROW, COLUMN, LARGE_COLUMN)
)
然后,我们在Content()中调用 LocalSize.current来查看当前组件的大小,根据当前组件的大小显示不同的布局。具体代码如下:
@Composable
override fun Content() {
val list = listOf(ACTION_ACTIVITY, ACTION_SERVICE, ACTION_BROADCAST, ACTION_CALLBACK)
when (LocalSize.current) {
SMALL_BOX, BIG_BOX, VERY_BIG_BOX -> {
WidgetBoxView(list)
}
ROW, LARGE_ROW -> {
WidgetRowView(list)
}
COLUMN, LARGE_COLUMN -> {
WidgetColumnView(list)
}
}
}
相关的UI代码如下。
@Composable
fun WidgetRowView(
list: List<String>
) {
Row(
modifier = GlanceModifier
.fillMaxSize()
.cornerRadius(24.dp)
.background(Color(0xfff1f1f1)),
horizontalAlignment = Alignment.Horizontal.CenterHorizontally,
verticalAlignment = Alignment.CenterVertically
) {
list.forEach { str ->
Button(
text = str,
onClick = getAction(str, LocalContext.current)
)
}
}
}
4. 设置GlanceAppWidgetReceiver
我们需要继承GlanceAppWidgetReceiver类。然后重写glanceAppWidget变量的get方法。
在get方法中返回上面提到的继承自GlanceAppWidget的你创建的类。
在我这个例子中是返回GlanceWidget()。
需要这一步的原因是让App和Glance小组件进行连接。
具体代码如下。
class GlanceReceiver : GlanceAppWidgetReceiver() {
override val glanceAppWidget: GlanceAppWidget
get() = GlanceWidget()
}
5. 设置actions
开发者可以使用Glance提供的如下方法来调用Broadcast, Service, Activity和Callback。
- actionStartBroadcast
- actionStartService
- actionStartActivity
- actionRunCallback
在这里我只展示如何实现Callback的调用,关于其他的方法的调用请查看我的GitHub。
首先,我们需要创建一个类且继承ActionCallback, 然后重写onRun方法。
class GlanceCallbackAction : ActionCallback {
override suspend fun onRun(context: Context, glanceId: GlanceId, parameters: ActionParameters) {
Handler(context.mainLooper).post() {
val parameter = parameters[GlanceWidget.ACTION_PARAMETERS_KEY]
Toast.makeText(context, "GlanceClickAction, parameter: $parameter", Toast.LENGTH_LONG)
.show()
}
}
}
之后,我们需要在按钮的clickable中去实现调用ActionCallback的代码。如果想要传递参数,需要使用actionParametersOf参数。actionParameter本质上是HashMap, 所以需要以Key和Value的方式放入需要传递的参数。具体代码如下:
actionRunCallback(
GlanceCallbackAction::class.java,
parameters = actionParametersOf(ACTION_PARAMETERS_KEY to str)
)
val ACTION_PARAMETERS_KEY = ActionParameters.Key<String>("parameters_keys")
6. 在AndroidManifest文件中设置相关信息
我们不光要为上面的提到的service, broadcast等相关组件添加信息,还要把在小题目4中提到的GlanceAppWidgetReceiver的信息添加到AndroidManifest.xml文件中。
<manifest>
<application>
......
<receiver
android:name=".GlanceReceiver"
android:enabled="@bool/glance_appwidget_available"
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_info" />
</receiver>
<receiver
android:name=".GlanceBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.hyejeanmoon.glancedemo" />
</intent-filter>
</receiver>
<service android:name=".GlanceService" />
</application>
</manifest>
7. 设置小组件的元数据
小组件的元数据指的是小组件相关的配置信息。该信息最终是要设置在AndroidManifest文件中的receiver中的。
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/glance_info" />
xml/glacen_info的具体代码如下。
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="<http://schemas.android.com/apk/res/android>"
android:minWidth="180dp"
android:minHeight="50dp"
android:resizeMode="horizontal|vertical"
android:targetCellWidth="3"
android:targetCellHeight="1"
android:widgetCategory="home_screen" />
widgetCategory: 声明小组件应该显示在哪个界面中。一共有home_screen(主屏幕)和keyguard(锁屏界面)两种。但是锁屏界面只能是Android5一下才可以设置,所以现在基本上只能设置主屏幕了。
targetCellWidth, targetCellHeight: 在Android12中新加的属性,声明组件应该以怎样的长高来显示。
previewImage: 设置小组件的预览图片,该图片会显示在选择小组件时的界面中。
|