Jetpack架构组件学习(6)——使用Glance实现桌面小组件
公司陆续整了几个Compose写的app,有个小组件的功能,顺便试了下Jetpack库里的Glance框架
感觉与原来的Remoteview差点意思,不过点击事件的使用比Remoteview要方便不少
PS: 如果想看Remoteview实现的小组件,可以参考我的此文Android 桌面小组件使用-Stars-One的杂货小窝
基本使用
1.添加依赖
添加Glance依赖:
// For AppWidgets support
implementation "androidx.glance:glance-appwidget:1.1.0"
// For interop APIs with Material 3
implementation "androidx.glance:glance-material3:1.1.0"
// For interop APIs with Material 2
implementation "androidx.glance:glance-material:1.1.0"
2.正常的相关设置
xml文件夹添加小组件widget_info.xml配置:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:targetCellWidth="2"
android:targetCellHeight="2"
android:minWidth="250dp"
android:minHeight="250dp"
android:updatePeriodMillis="0"
android:initialLayout="@layout/glance_default_loading_layout"
tools:targetApi="s">
</appwidget-provider>
清单文件配置:
<receiver android:name=".appwidgets.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/widget_info" />
</receiver>
3.创建widget对象和实现界面
需要注意的几点:
- 界面的Row,Column,Text等,注意要使用Glance的包下的,否则会无法正常显示界面
官方也是说明了,Row,Box,Column实际最后创建的对象对应的Linearlayout和Framelayout
- 点击跳转的对应actionStartActivity方法,实际是返回一个Action对象 通过
GlanceModifier.clickable(actionStartActivity(MainActivity::class.java))进行对应跳转
除了activity外,还能启动Service,BoardCast,详见此文档处理用户互动 | Jetpack Compose | Android Developers
- 关于背景圆角的方法,目前采用Box里面套一个Image和具体内容实现,Image去加载我们drawable里的矢量图对象(shape的那种)来实现
- remember在里面可用,但如果结合animateColorAsState这种动画效果,实际上并没有效果(只是单纯的变更,没有中间过渡过程)
class MyAppWidgetReceiver : GlanceAppWidgetReceiver() {
//MyAppWidget里就是类似我们remoteview的创建
override val glanceAppWidget: GlanceAppWidget = MyAppWidget()
}
class MyAppWidget : GlanceAppWidget() {
override suspend fun provideGlance(context: Context, id: GlanceId) {
// In this method, load data needed to render the AppWidget.
// Use `withContext` to switch to another thread for long running
// operations.
provideContent {
val upSpeed by DataRespotiy.upSpeed.asFlow().collectAsState(initial = 0L)
val downloadSpeed by DataRespotiy.downloadSpeed.asFlow().collectAsState(initial = 0L)
Box(GlanceModifier.fillMaxSize()) {
Image(provider = ImageProvider(R.drawable.app_widget_bg), contentDescription = null, modifier = GlanceModifier.fillMaxSize())
Column(GlanceModifier.fillMaxSize()) {
Spacer(GlanceModifier.height(28.dp))
Row(GlanceModifier.fillMaxWidth().padding(horizontal = 20.dp)) {
androidx.glance.Image(provider = ImageProvider(R.mipmap.logo), contentDescription = null, modifier = GlanceModifier.size(108.dp))
Spacer(modifier = GlanceModifier.width(24.dp))
Column(GlanceModifier.defaultWeight()) {
Row(modifier = GlanceModifier.wrapContentHeight(), horizontalAlignment = Alignment.End, verticalAlignment = Alignment.Vertical.CenterVertically) {
Text(text = "${upSpeed} Kb/s", style = TextStyle(color = ColorProvider(APP_Primary_color), fontSize = 22.sp))
Spacer(modifier = GlanceModifier.width(4.dp))
androidx.glance.Image(provider = ImageProvider(R.drawable.icon_upload_widget), contentDescription = null, modifier = GlanceModifier.size(32.dp))
}
Spacer(modifier = GlanceModifier.height(18.dp))
Row(modifier = GlanceModifier, horizontalAlignment = Alignment.End, verticalAlignment = Alignment.Vertical.CenterVertically) {
Text(text = "${downloadSpeed} Kb/s", style = TextStyle(color = ColorProvider(APP_Bigfile_color), fontSize = 22.sp))
Spacer(modifier = GlanceModifier.width(4.dp))
androidx.glance.Image(provider = ImageProvider(R.drawable.icon_down_widget), contentDescription = null, modifier = GlanceModifier.size(32.dp))
}
}
}
Spacer(GlanceModifier.height(28.dp))
Box(modifier = GlanceModifier.fillMaxWidth().defaultWeight()) {
Image(provider = ImageProvider(R.drawable.app_widget_bg1), contentDescription = null, modifier = GlanceModifier.fillMaxSize())
Row(
modifier = GlanceModifier.fillMaxSize()
.padding(horizontal = 20.dp,16.dp), horizontalAlignment = Alignment.CenterHorizontally
) {
val modifier = GlanceModifier.defaultWeight()
//todo 不同的item类型
repeat(3) { index ->
Row(modifier, horizontalAlignment = Alignment.CenterHorizontally, verticalAlignment = Alignment.Vertical.CenterVertically) {
androidx.glance.Image(
provider = ImageProvider(R.drawable.icon_net_test), contentDescription = null, modifier = GlanceModifier
.size(108.dp)
.clickable(actionStartActivity(MainActivity::class.java))
)
}
Spacer(GlanceModifier.width(20.dp))
}
}
}
}
}
}
}
}
其他补充
更新小组件方法:
val manager = GlanceAppWidgetManager(application)
val widget = MyAppWidget()
val glanceIds = manager.getGlanceIds(widget.javaClass)
glanceIds.forEach { glanceId ->
widget.update(application, glanceId)
}
//第二种方式(实际上和上面的方法是一样的,下面这个是官方给我们封装的另外个方法)
MyAppWidget().updateAll(application)
参考
Jetpack架构组件学习(6)——使用Glance实现桌面小组件的更多相关文章
- Android-Widget桌面小组件
1, 掌握Widget的用:Widget的用途,能够添加到手机桌面的程序 2, Widget的特点和用法步骤: 特点:快捷,方便,个性化,可自定义功能,可及时控制更新Widget显示内容 3, 用法步 ...
- iOS阶段学习第34天笔记(UI小组件 UISegment-UISlider-UIStepper-UIProgressView-UITextView介绍)
iOS学习(UI)知识点整理 一.UI小组件 1.UISegmentedControl 分段选择器 实例代码 - (void)viewDidLoad { [super viewDidLoad]; / ...
- Android桌面小组件的使用
一:建立一个类继承AppWidgetProvider 二:建立AWP的布局文件: 布局自己定义一个,但是在使用控件上是有要求的: 以上是Widget目前支持的控件. 三:编写AWP的信息文件:需要在r ...
- Android开发工程师文集-1 小时学会Widget小组件开发
前言 大家好,给大家带来Android开发工程师文集-1 小时学会Widget小组件开发的概述,希望你们喜欢 学会用Widget (小组件) Widget小组件很方便,很快捷,可以个性化,自己定制,相 ...
- Vue框架——页面组件中使用小组件
小组件在components文件夹中,页面组件在views文件夹中 一.先写小组件的vue,比如text.vue(在template设置模板渲染,style设置样式) <template> ...
- Jetpack架构组件学习(1)——LifeCycle的使用
原文地址:Jetpack架构组件学习(1)--LifeCycle的使用 | Stars-One的杂货小窝 要看本系列其他文章,可访问此链接Jetpack架构学习 | Stars-One的杂货小窝 最近 ...
- Jetpack架构组件学习(2)——ViewModel和Livedata使用
要看本系列其他文章,可访问此链接Jetpack架构学习 | Stars-One的杂货小窝 原文地址:Jetpack架构组件学习(2)--ViewModel和Livedata使用 | Stars-One ...
- Jetpack架构组件学习(3)——Activity Results API使用
原文地址:Jetpack架构组件学习(3)--Activity Results API使用 - Stars-One的杂货小窝 技术与时俱进,页面跳转传值一直使用的是startActivityForRe ...
- Jetpack架构组件学习(4)——APP Startup库的使用
最近在研究APP的启动优化,也是发现了Jetpack中的App Startup库,可以进行SDK的初始化操作,于是便是学习了,特此记录 原文:Jetpack架构组件学习(4)--App Startup ...
- 还在一个模块打天下嘛?你知道引入Jetpack架构后,你的App会发生哪些奇妙的变化吗?
前言 上篇文章我给大家分享了我对Android架构的理解,从思想层面去讲述架构的演进过程.很多小伙伴读完后拍手叫好,表示还想听我讲一下对Jetpack 架构的看法,本着帮人帮到底的精神,今天我将再次动 ...
随机推荐
- 解读Karmada多云容器编排技术,加速分布式云原生应用升级
本文分享自来源:<华为云DTSE>第五期开源专刊,作者:任洪彩 华为云高级软件工程师,Karmada社区Maintainer. 管理和协调跨多个云平台的容器化应用是当前企业面临的复杂性 ...
- 低功耗4G模组Air780E快速入门:使用文件系统存储温湿度数据
伙伴们,今天我们来学习合宙低功耗4G模组Air780E快速入门之使用文件系统存储温湿度数据. 一.编写脚本 1.1 准备资料 780E开发板购买链接 780E开发板设计资料 LuatOS-Air7 ...
- ElementUI ---- dialog点击取消后蒙遮层不消失
场景: 页面A打开了 dialog, 然后点击 页面A dialog 的按钮 跳转到 页面B,并且打开页面B的 dialog 但是页面B的 dialog 关闭后,蒙遮层并没消失(已经设置了 :appe ...
- Java Concurrent
本文节选自 Effective Java by Joshua Bloch 和 Concurrent Programming in Java by Doug Lea. 1.1 概述 多线程程序设计比单线 ...
- 关于《完全手册Excel VBA典型实例大全——通过368个例子掌握》随书样例的下载
按照早先下载的电子教程查看和编写vba,有些例子使用运行错误,想着看看原始文件.容易看到,网上有提供的doc或者pdf文档,都不完整,可能是{完全手册Excel_VBA典型实例大全:通过368个例子掌 ...
- 4-CSRF漏洞渗透与防御
1.什么是CSRF漏洞 Cross-Site Request Forgery 跨站请求伪造 从一个第三方的网站,利用其他网站生效的cookie,直接请求服务器的某一个接口,导致攻击发生! 2.CSRF ...
- kettle 使用 CARTE 执行
在执行KETTLE 任务的时候,可以使用本地执行,或者使用carte server执行. 1.启动carte server .\Carte.bat localhost 8080 2.配置子服务器 这里 ...
- 【分块】LibreOJ 6278 数列分块入门2
题目 https://loj.ac/p/6278 题解 将 \(n\) 个元素的数组 \(a\) 按块长 \(\sqrt{n}\) 进行分块处理.为每个块设置一个懒添加标记 \(add[i]\),代表 ...
- WebP图片使用踩坑
前情 WebP是一种同时提供了有损压缩与无损压缩(可逆压缩)的图片文件格式,最初在2010年发布,目标是减少文件大小,相较于传统的 PNG.JPG,甚至是动图 GIF 的格式,WebP 比它们的空间更 ...
- ABAP开发规范V1.0
1. 概要 1.1目的 该文档定义了在开发与维护ABAP程序过程中必须遵守的规范与标准.该文档应当被视为一个动态的文档,该文档会根据需要进行增补和修订. 开发规范的重要作用在于保持整个开发团队的开发风 ...