一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第8天 点击查看活动详情。
一、简单使用
在Compose中使用Image展示图片,我们来实际使用一下:
@Composable
fun TestImage() {
Image(
painter = painterResource(id = R.drawable.ic_launcher_background),
contentDescription = "我是描述"
)
}
@Preview(showBackground = true, widthDp = 1080, heightDp = 1920)
@Composable
fun TestImagePreview() {
TestImage()
}
我们来看一下预览效果:
下面我们一起看看Image的源码,来解锁Image的更多用法:
@Composable
fun Image(
bitmap: ImageBitmap,
contentDescription: String?,
modifier: Modifier = Modifier,
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.Fit,
alpha: Float = DefaultAlpha,
colorFilter: ColorFilter? = null
)
@Composable
fun Image(
painter: Painter,
contentDescription: String?,
modifier: Modifier = Modifier,
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.Fit,
alpha: Float = DefaultAlpha,
colorFilter: ColorFilter? = null
)
我们可以看到这里有多个重载方法,这几个方法除了第一个参数不同以外,其他参数都是一样的。我们具体来看一下:
1. ImageBitmap
bitmap参数类型为ImageBitmap,而不是Bitmap。Compose中有提供一个Bitmap的扩展方法,可以直接Bitmap转成ImageBitmap:
@Composable
fun TestImage() {
val bitmap = BitmapFactory.decodeFile("图片的路径")
Image(
bitmap = bitmap.asImageBitmap(),
contentDescription = "我是描述"
)
}
2. Painter
painter参数类型为Painter,它是一个抽象类,有三个子类:
我们来看一下上面例子里使用的painterResource相关的源码:
@Composable
fun painterResource(@DrawableRes id: Int): Painter {
val context = LocalContext.current
val res = context.resources
val value = remember { TypedValue() }
res.getValue(id, value, true)
val path = value.string
// Assume .xml suffix implies loading a VectorDrawable resource
return if (path?.endsWith(".xml") == true) {
val imageVector = remember(path, id) {
loadVectorResource(context.theme, res, id)
}
rememberVectorPainter(imageVector)
} else {
// Otherwise load the bitmap resource
val imageBitmap = remember(path, id) {
loadImageBitmapResource(res, id)
}
BitmapPainter(imageBitmap)
}
}
private fun loadVectorResource(theme: Resources.Theme, res: Resources, id: Int): ImageVector {
@Suppress("ResourceType") val parser = res.getXml(id)
if (parser.seekToStartTag().name != "vector") {
throw IllegalArgumentException(errorMessage)
}
return loadVectorResourceInner(theme, res, parser)
}
private fun loadImageBitmapResource(res: Resources, id: Int): ImageBitmap {
try {
return ImageBitmap.imageResource(res, id)
} catch (throwable: Throwable) {
throw IllegalArgumentException(errorMessage)
}
}
官方为我们提供了这种便捷的方法,让我们可以更快捷的使用。但是要注意的是painterResource方法只能传递Drawable下的资源文件。我们在使用的时候直接传入资源id就可以了。
2. 设置图片样式
1. alignment
alignment是可选的对齐参数,其类型为Alignment,用于将Image放置在由宽度和高度定义的范围内。看一下实际用法:
@Composable
fun TestImage() {
Image(
painter = painterResource(id = R.drawable.ic_launcher_background),
contentDescription = "我是描述",
alignment = Alignment.Center
)
}
2. contentScale
contentScale用来设置横纵缩放比,参数类型为ContentScale。默认值为ContentScale.Fit:保持原图片的宽高比。还是先看一下源码来解锁一下其他几种类型:
@Stable
interface ContentScale {
// 计算比例银子以相互独立的应用于水平轴和垂直轴,以使源与给定的目标适配
fun computeScaleFactor(srcSize: Size, dstSize: Size): ScaleFactor
companion object {
//保持图片的宽高比,以使图片的宽度和高度都等于或大于目标的相应尺寸
@Stable
val Crop
// 保持图片的宽高比,使图片的宽高都小于等于目标尺寸
@Stable
val Fit
// 高度相等,宽度自适应
@Stable
val FillHeight
//宽度相等,高度自适应
@Stable
val FillWidth
//如果图片大于目标尺寸,则等比缩小, 如果小于或等于,则不发生变化
@Stable
val Inside
// 不做任何操作
@Stable
val None = FixedScale(1.0f)
// 拉伸效果
@Stable
val FillBounds
}
}
有了这些注释后,使用起来就方便多了,视具体情况来选择使用。
3. alpha
图片的透明度,类型为Float。默认值为1.0f:
const val DefaultAlpha: Float = 1.0f
示例: 我们看一个效果,顶层放一个Image,下面放一个Text,我们先看Image的alpha=1.0f的情况:
@Composable
fun TestImage() {
Box(modifier = Modifier.background(color = Color.Red)) {
Text(text = "沐枫")
Image(
painter = painterResource(id = R.drawable.ic_launcher_background),
contentDescription = "我是描述",
alpha = 1.0f
)
}
}
然后我们在把alpha改成0.5f在试试:
@Composable
fun TestImage() {
Box(modifier = Modifier.background(color = Color.Red)) {
Text(text = "沐枫")
Image(
painter = painterResource(id = R.drawable.ic_launcher_background),
contentDescription = "我是描述",
alpha = 0.5f
)
}
}
我们改成半透明的时候,就可以看到下面的Text控件了
4. colorFilter
参数类型为ColorFilter,可以为图片进行着色,也可以为Image设置颜色矩阵,还可以为Image创建简单的照明效果。先看源码:
@Immutable
class ColorFilter internal constructor(internal val nativeColorFilter: NativeColorFilter) {
companion object {
// 创建一个颜色滤镜,该滤镜作为第二参数给出的混合模式
// 源颜色是第一个参数指定的颜色,目标颜色是来自要合成的涂层颜色
@Stable
fun tint(color: Color, blendMode: BlendMode = BlendMode.SrcIn): ColorFilter =
actualTintColorFilter(color, blendMode)
// 创建一个ColorFilter以通过4*5颜色矩阵转换颜色
// 改滤镜可用于更改像素饱和度,从YUV转换为RGB等
@Stable
fun colorMatrix(colorMatrix: ColorMatrix): ColorFilter =
actualColorMatrixColorFilter(colorMatrix)
// 创建可用于模拟简单照明效果的colorFilter
// ColorFilter由两个参数定义: 一个参数用于乘以源颜色,另一个参数用于添加至源颜色
@Stable
fun lighting(multiply: Color, add: Color): ColorFilter =
actualLightingColorFilter(multiply, add)
}
}
写个例子试试:
Image(
painter = painterResource(id = R.drawable.ic_launcher_background),
contentDescription = "我是描述",
colorFilter = ColorFilter.tint(Color.Red)
)
3. 显示网络图片
显示网络图片之前,我们需要依赖一个库: Jetpack Compose - Coil (coil-kt.github.io)
implementation "io.coil-kt:coil-compose:2.0.0-rc03"
coil是一个完全使用Kotlin编写的,一个很新的图片加载库,使用了Kotlin协程,图片网络请求方式默认为OkHttp。特点:速度快,在内存、图片存储、图片采样、Bitmap重用、暂停/取消下载等细节方面都做了大幅优化;足够轻,只有大概1500个核心方法。最最重要的是,coil支持Compose,里面实现了网络图片的可组合项。
实际用法:
AsyncImage(
model = "https://pic3.zhimg.com/v2-58d652598269710fa67ec8d1c88d8f03_r.jpg?source=1940ef5c",
contentDescription = "我是描述"
)
可以看到AsyncImage的用法很简单,只需要传入图片地址即可。由于网络图片无法预览查看,我们要运行看效果:
上面附带了Coil的官方文档,大家可以前往学习解锁Coil在Compose中更多的用法
最后
感谢你看到最后, 最后再说两点~
①如果你持有不同的看法,欢迎你在文章下方进行留言、评论。
②如果对你有帮助,或者你认可的话,欢迎给个小点赞,支持一下~
我是沐小枫,一个热爱学习、热爱编程的山东人
(文章内容仅供学习参考, 如有侵权,非常抱歉,请立即联系作者删除。)