【自学Jetpack Compose 系列】Compose控件(五)Compose中的“ImageView”

1,084 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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.png

下面我们一起看看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,它是一个抽象类,有三个子类:

image.png 我们来看一下上面例子里使用的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
        )
    }
}

image.png

然后我们在把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
        )
    }
}

image.png 我们改成半透明的时候,就可以看到下面的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)
)

image.png

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的用法很简单,只需要传入图片地址即可。由于网络图片无法预览查看,我们要运行看效果:

image.png

上面附带了Coil的官方文档,大家可以前往学习解锁Coil在Compose中更多的用法

最后

感谢你看到最后, 最后再说两点~
①如果你持有不同的看法,欢迎你在文章下方进行留言、评论。
②如果对你有帮助,或者你认可的话,欢迎给个小点赞,支持一下~
我是沐小枫,一个热爱学习、热爱编程的山东人

(文章内容仅供学习参考, 如有侵权,非常抱歉,请立即联系作者删除。)