原文地址 Jetpack Compose学习(4)——Image(图片)使用及Coil图片异步加载库使用 | Stars-One的杂货小窝
本篇讲解下关于Image的使用及使用Coil开源库异步加载网络图片显示
本系列以往文章请查看此分类链接Jetpack compose学习
Image使用
首先,先看下参数
fun Image(painter: Painter,contentDescription: String?,modifier: Modifier = Modifier,alignment: Alignment = Alignment.Center,contentScale: ContentScale = ContentScale.Fit,alpha: Float = DefaultAlpha,colorFilter: ColorFilter? = null)
可以看到Image图片的参数大体上是和是Icon一样,基本使用呢,和上一篇讲的Icon类似,我们加载一张本地的图片,代码如下
Image(painter = painterResource(id = R.drawable.download),contentDescription = null)
比较基础的参数这里就不再赘述了,这里主要讲解下面的其他参数
1.alignment
图片对齐方向,前提是Image设置了宽高,取值为
Alignment
的定义的枚举
设置宽高是通过
Modifier.size()
来设置
取值有图中几种:
注意: 图中特意方框围起来的,其返回值不是
Alignment
类型的,这几个并不能取,你选了的话编辑器也会贴心的给出错误提示的 笑
这个alignment参数有九种取值,将一个固定的长方形分为九块,如下图所示
Column() {//为了便于区分,这里使用Modifier添加了个黄色的背景Image(modifier = Modifier.size(200.dp,300.dp).background(color = Color.Yellow),//图片自己随便找张即可painter = painterResource(id = R.drawable.download),contentDescription = null,alignment = Alignment.Center)}
可以看到实际效果中,图片是居中对齐的,其他效果也就不一一展示了
2.contentScale
图片缩放设置,和原生的ImageView的scaleType属性类似,取值是
ContentScale
的枚举,默认是
ContentScale.Fit
(即自适应)
-
ContentScale.Crop
裁剪
-
ContentScale.FillBounds
拉伸图片宽高填满形状
-
ContentScale.FillHeight
拉伸图片高度填满高度
-
ContentScale.FillWidth
拉伸图片宽填满宽度
-
ContentScale.Fit
-
ContentScale.Inside
-
ContentScale.None
不缩放
这个也是需要Image设置宽高才可以看出效果
下面演示各种不同效果的Image(由于Fit是默认的,下面就没展示出来了)
代码如下
Column(Modifier.verticalScroll(rememberScrollState())) {//为了便于区分,这里使用Modifier添加了个黄色的背景Image(modifier = Modifier.size(200.dp, 150.dp).background(color = Color.Yellow),painter = painterResource(id = R.drawable.download),contentDescription = null,contentScale = ContentScale.Crop)Image(modifier = Modifier.size(200.dp, 150.dp).background(color = Color.Yellow),painter = painterResource(id = R.drawable.download),contentDescription = null,contentScale = ContentScale.Inside)Image(modifier = Modifier.size(200.dp, 150.dp).background(color = Color.Yellow),painter = painterResource(id = R.drawable.download),contentDescription = null,contentScale = ContentScale.FillBounds)Image(modifier = Modifier.size(200.dp, 150.dp).background(color = Color.Yellow),painter = painterResource(id = R.drawable.download),contentDescription = null,contentScale = ContentScale.FillHeight)Image(modifier = Modifier.size(200.dp, 150.dp).background(color = Color.Yellow),painter = painterResource(id = R.drawable.download),contentDescription = null,contentScale = ContentScale.FillWidth)Image(modifier = Modifier.size(200.dp, 150.dp).background(color = Color.Yellow),painter = painterResource(id = R.drawable.download),contentDescription = null,contentScale = ContentScale.None)}
3.alpha
透明度,数值类型为float,数值范围为
0f-1f
之间,默认是1f
如下代码所示
Image(modifier = Modifier.size(200.dp, 150.dp).background(color = Color.Yellow),painter = painterResource(id = R.drawable.download),contentDescription = null,alpha = 1f)Image(modifier = Modifier.size(200.dp, 150.dp).background(color = Color.Yellow),painter = painterResource(id = R.drawable.download),contentDescription = null,alpha = 0.5f)
效果如下图所示
4.colorFilter
着色效果,可以使用颜色对图片进行混合加工,有下面三种方法进行设置
-
ColorFilter.tint(Color, BlendMode)
着色效果
-
ColorFilter.lighting(Color,Color)
-
ColorFilter.colorMatrix(colorMatrix)
这个我不是研究太多,各位可以百度参考下其他大神写的文章
这里就讲个小例子,改变图片的颜色
美工给的图标有些是单一的颜色,比如说选中后是蓝色,不选中是灰色的
但有时候项目需要更改颜色,如选中后要改为绿色,这个时候得要美工再次切图,十分麻烦
这个时候我们可以这个属性,去修改颜色,如下面代码
Image(modifier = Modifier.size(200.dp, 150.dp),painter = painterResource(id = R.drawable.eye_show),contentDescription = null,alpha = 1f,colorFilter = ColorFilter.tint(color = Color.Green, BlendMode.SrcAtop))
效果:
R.drawable.eye_show
图片原本是灰色的,现在被我们渲染成了绿色,这种方法比较适合那种单一颜色的图标文件
而且有了这种方法,我们甚至只需要一种灰色的图标即可,蓝色的图标就不需要,可以省下不少apk的体积大小
至于更多内容,需要各位去研究啦…:smile:
Coil图片异步加载库使用
上述我们一直使用的是本地图片,如果是网络图片,该怎么办呢?以往我们都是使用Glide加载,但现在由于Compose是采用State状态监测机制去渲染UI,所以如果我们自己去实现就会十分麻烦
刚好现在已经有大神整了框架,我们拿来使用即可
Coil这个框架是
Accompanist
的子库,那么
Accompanist
是什么呢?
Accompanist 是一组旨在扩充
Jetpack Compose
功能的第三方库集合,这个库中所提供的功能是开发者普遍需要的。
注: 写这篇文章后发现,在
Accompanist
的
0.16.0
版本更新日志中,移除了
Coil
等图片加载的库,
Coil
好像是单独出来了,下面是摘自官方的更新说明:
Coil, Glide and Image Loading Core have been removed
After being deprecated in v0.14.0, it\’s time to remove the
coil
,
glide
and
imageloading-core
libraries. Some discussion about this can be seen on the Kotlin Slack: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1627482619344000.
TL;DR: the recommendation is to move to Coil Compose.
迁移到此开源库coil-kt/coil: Image loading for Android backed by Kotlin Coroutines.
基本使用
基本流程,先导依赖
implementation("io.coil-kt:coil:1.3.2")
图片的
painter
参数使用
rememberImagePainter
此方法,可传入一个网络图片
Image(painter = rememberImagePainter("https://img0.baidu.com/it/u=312301072,1324966529&fm=26&fmt=auto&gp=0.jpg"),contentDescription = null,modifier = Modifier.size(128.dp))
PS:不要忘记加网络权限
<uses-permission android:name="android.permission.INTERNET" />
哦!!
效果:
占位图 过渡及圆形裁剪
- 占位图 placeholder
- 过渡 transitions
- 变化效果 transformations
由于是网络图片,我们在预览界面是无法看到有图片的,这个时候我们可以考虑设置下占位图片,好方便调试UI
Image(modifier = Modifier.size(128.dp),painter = rememberImagePainter(data = "https://img0.baidu.com/it/u=312301072,1324966529&fm=26&fmt=auto&gp=0.jpg",builder = {//占位图placeholder(R.drawable.placeholder)//淡出效果crossfade(true)//圆形效果transformations(CircleCropTransformation())}),contentDescription = null,)
预览界面可以看到占位图
加载网络的图片过渡效果:
可能图中看不出圆形裁剪,我们可以加上背景看看,图片其实已经是被裁剪了的
目前,Coil自带了两种过渡效果:
-
CrossfadeTransition
从当前可绘制到成功/错误可绘制的淡入淡出(即上文代码出现的
crossfade
)
-
Transition.NONE
它在Target没有动画的情况下立即设置可绘制对象。想要实现自定义,可以参考下CrossfadeTransition源代码,本文就不过多展开了
transformations主要是变化的意思,官方的解释是
transformations允许您在Drawable从请求返回之前修改图像的像素数据。
Coil默认提供了4种类型
blur
(高斯模糊)
circle crop
(圆形裁剪)
grayscale
(灰度)
rounded corners
(圆角)
对应的代码如下:
//radis是外层圆角,sample为高斯模糊的程度(要大于1f即可)BlurTransformation(context,radius,sample)//灰度GrayscaleTransformation()//圆角RoundedCornersTransformation(0.8f)
效果如下所示
源代码:
@ExperimentalCoilApi@Preview(showBackground = true)@Composablefun ImagePageDemo() {val context = LocalContext.currentComposeDemoTheme {Column(Modifier.verticalScroll(rememberScrollState())) {/*Image(painter = rememberImagePainter("https://img0.baidu.com/it/u=312301072,1324966529&fm=26&fmt=auto&gp=0.jpg"),contentDescription = null,modifier = Modifier.size(128.dp),)*/Image(modifier = Modifier.size(128.dp).background(Color.Blue),painter = rememberImagePainter(data = "https://img0.baidu.com/it/u=312301072,1324966529&fm=26&fmt=auto&gp=0.jpg",builder = {crossfade(true)placeholder(R.drawable.placeholder)transformations(BlurTransformation(context,0.1f,2f))}),contentDescription = null,)Image(modifier = Modifier.size(128.dp).background(Color.Blue),painter = rememberImagePainter(data = "https://img0.baidu.com/it/u=312301072,1324966529&fm=26&fmt=auto&gp=0.jpg",builder = {crossfade(true)placeholder(R.drawable.placeholder)transformations(GrayscaleTransformation())}),contentDescription = null,)Image(modifier = Modifier.size(128.dp).background(Color.Blue),painter = rememberImagePainter(data = "https://img0.baidu.com/it/u=312301072,1324966529&fm=26&fmt=auto&gp=0.jpg",builder = {crossfade(true)placeholder(R.drawable.placeholder)transformations(RoundedCornersTransformation(0.8f))}),contentDescription = null,)}}}
加载gif
需要添加依赖插件包
implementation("io.coil-kt:coil-gif:1.3.2")
val context = LocalContext.currentval imageLoader = ImageLoader.Builder(context).componentRegistry {add(GifDecoder())add(SvgDecoder(context))}.build()Image(modifier = Modifier.size(128.dp).background(Color.Blue),painter = rememberImagePainter(data = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F01bdd05a436090a80121974142c9f3.gif&refer=http%3A%2F%2Fimg.zcool.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1634225053&t=eaa097d38a32f901b7096fae16bfb98f",builder = {//加了这个解码,如果图片是jpg等格式,是没法成功解析出来的decoder(GifDecoder())crossfade(true)placeholder(R.drawable.placeholder)}),contentDescription = null,)
效果如下所示
PS:上述代码是我自己大概摸索出来的,没想到竟然能用…:confused:
官方给的文档一直没有个标准的使用例子,也不知道上面这样写对不对,仅供参考:sweat:
下面这个好像是正确的代码,image可以同时支持加载gif或者是jpg等图片
Column() {val context = LocalContext.current//创建图片加载器val myImageLoader = ImageLoader.Builder(context).componentRegistry {//这里可以加多个图片解码器add(GifDecoder())}.build()Image(modifier = Modifier.size(128.dp).background(Color.Blue),painter = rememberImagePainter(data = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F01bdd05a436090a80121974142c9f3.gif&refer=http%3A%2F%2Fimg.zcool.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1634225053&t=eaa097d38a32f901b7096fae16bfb98f",//设置图片加载器imageLoader = myImageLoader,builder = {crossfade(true)placeholder(R.drawable.placeholder)}),contentDescription = null,)}
加载svg
如gif一样,也是要加个插件依赖,之后注册即可
implementation("io.coil-kt:coil-svg:1.3.2")
val context = LocalContext.current//创建图片加载器val myImageLoader = ImageLoader.Builder(context).componentRegistry {add(GifDecoder())add(SvgDecoder(context))}.build()
补充
下面的都是一样的,不过使用Coil加载图片会出现图片放大后失真问题,所以有另外款开源库推荐landscapist
implementation "com.github.skydoves:landscapist-coil:1.3.2"
CoilImage(imageModel = "https://coil-kt.github.io/coil/images/coil_logo_black.svg",contentDescription = null,imageLoader = myImageLoader)
参考
- Jetpack Compose – Image_乐翁龙-CSDN博客
- Image – Jetpack Compose中文文档
- Accompanist中文翻译文档 – Jetpack Compose中文文档
- Accompanist官方文档
- Coil官方文档之Jetpack Compose –
- Android-使用 SetColorFilter 神奇地改变图片的颜色_段浅浅的博客-CSDN博客_setcolorfilter