Compose布局之Image控件使用详解:加载网络图片与内容缩放

这篇具有很好参考价值的文章主要介绍了Compose布局之Image控件使用详解:加载网络图片与内容缩放。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

阅读本文需要一定compose基础,如果没有请移步Jetpack Compose入门详解(实时更新)

本文介绍Compose中Image控件的基本概念以及深入了解。根据官网教程总结,如有不对请在评论区指教


一、基础认识🧩

Image(){} 是一个类似xml布局中 imageView的控件,主要用于展示图片,它包含了如下属性参数
Compose,Image控件,加载网络图片,contentScale内容缩放

  • painter 需要传入的图片,可以是矢量图,可以是位图 ,常用方法就是painterResource(id = R.mipmap.xxx)

  • contentDescription 图片的描述,如果不是重要的图片展示可以为null

  • modifier用于调整布局算法或绘制装饰内容(例如背景)的修饰符,下文会表述一些image的modifier使用

  • alignment 可选的对齐参数,用于将Painter放置在由宽度和高度定义的给定边界内。默认居中,这个属性比较基础,本文不会过多描述

  • contentScale 可选的缩放参数,用于确定当边界的大小与Painter的固有大小不同时要使用的纵横比缩放,默认均匀缩放图片,并保持宽高比。如果内容小于指定大小,系统会放大图片以适应边界。

  • alpha在屏幕上渲染时可选不透明度,默认情况下,图片将完全不透明

  • colorFilter在屏幕上渲染时应用于Painter的可选colorFilter,可用于更改图片中各个像素的输出。以达到滤镜的效果

一般使用代码示例:

  Image(
                painter = painterResource(id = R.mipmap.girl) ,
                contentDescription = "小姐姐"
            )


效果如下
Compose,Image控件,加载网络图片,contentScale内容缩放


二、contentScale内容缩放🗽

1.为什么使用

上面的图片非常漂亮,但是在实际开发app中很多时候我们并不需要展示精美切像素那么高的位图,我们持续加载超过所需大小的图片可能会耗尽 GPU 缓存,从而导致界面渲染性能不佳。从而导致OutOfMemoryError;在这一点上,xml中的imageView和Compose中的Image都有这个问题,Image则可以通过contentScale属性来进行内容缩放和裁剪解决,不得不说的是,三方库在这个问题的解决上比原生控件更优秀

2.属性介绍

为了让读者更易懂contentScale内容缩放,我按照官方示例增加了图片的背景和边框,并且并排展示纵向和横向的图片

默认(ContentScale.Fit)

均匀缩放图片,并保持宽高比。如果内容小于指定大小,系统会放大图片以适应边界。

代码示例

 Row (
        Modifier.background(White),
        horizontalArrangement = Arrangement.Center ,
        verticalAlignment = Alignment.CenterVertically            ){
        val imageModifier = Modifier            .size(150.dp)
            .border(BorderStroke(1.dp, Black))
            .background(Yellow)
        Column {
            Image(
                painter = painterResource(id = R.mipmap.girl) ,
                contentDescription = "小姐姐",
                modifier = imageModifier            )
        }
        Column(
            Modifier.padding(start =  10.dp)
        ) {
            Image(
                painter = painterResource(id = R.mipmap.girl1) ,
                contentDescription = "小姐姐1",
                modifier = imageModifier            )
        }
    }


效果如下

Compose,Image控件,加载网络图片,contentScale内容缩放

这个时候图片等比缩小了,对比一开始的图片我们可以发现图片还是完整展示的

将图片居中裁剪到可用空间(ContentScale.Crop)

代码如下

    val imageModifier = Modifier        .size(150.dp)
        .border(BorderStroke(1.dp, Black))
        .background(Yellow)
    val contentScale = ContentScale.Crop    Row (
        Modifier.background(White),
        horizontalArrangement = Arrangement.Center ,
        verticalAlignment = Alignment.CenterVertically            ){
       
        Column {
            Image(
                painter = painterResource(id = R.mipmap.girl) ,
                contentDescription = "小姐姐",
                modifier = imageModifier,
                contentScale = contentScale            )
        }
        Column(
            Modifier.padding(start =  10.dp)
        ) {
            Image(
                painter = painterResource(id = R.mipmap.girl1) ,
                contentDescription = "小姐姐1",
                modifier = imageModifier,
                contentScale = contentScale            )
        }
    }


效果如下
Compose,Image控件,加载网络图片,contentScale内容缩放
这里我们可以看见图片将整个背景填充满了,无论横向还是纵向,看起来更饱满但这也导致我们失去了部分展示

缩放来源图片,保持宽高比不变,使边界与目标高度匹配。(ContentScale.FillHeight)

因为下面的所有代码示例只替换了 val contentScale 中的值,故后面的属性都只展示和描述效果

效果如下
Compose,Image控件,加载网络图片,contentScale内容缩放
可以看到为了和高度匹配,横向的图片被裁剪了一部分,而纵向的则不受影响

缩放来源图片,保持宽高比不变,使边界与目标宽度匹配。(ContentScale.FillWidth)

效果如下
Compose,Image控件,加载网络图片,contentScale内容缩放
与ContentScale.FillHeight相反,为了和宽度匹配,纵向的图片被裁剪了一部分,而横向的则不受影响

以非均匀方式垂直和水平缩放内容,以填充目标边界。(ContentScale.FillBounds)

用我个人的话来理解就是不裁剪图片并将图片拉伸至填充满整个Image控件,这样既可以完全展示图片,有让其填充满控件,缺点是图片容易失真,看起来贼丑

效果如下

Compose,Image控件,加载网络图片,contentScale内容缩放
怎么说呢,不太建议使用吧

缩放来源图片,使宽高保持在目标边界内。(ContentScale.Inside)

缩放来源图片,使宽高保持在目标边界内。如果来源图片在两个维度上都小于或等于目标,则其行为类似于“None”。内容始终包含在边界内。如果内容小于边界,则不会应用缩放。

效果如下
Compose,Image控件,加载网络图片,contentScale内容缩放
因为图片的关系看起来没什么效果(笑哭),不影响啊,不影响,理解了就行

不缩放。(ContentScale.None)

效果如下
Compose,Image控件,加载网络图片,contentScale内容缩放
因为原图比较大,所以不缩放就成这个样子了


三、将 Image 可组合项裁剪为某个形状🔰

这个其实归功于修饰符的属性

	Modifier .clip()


这个属性呢,主要是将图片或裁剪成圆形或者圆角的,之前的文章中也提到过将背景裁剪成圆角和圆形的大概使用方法为

		Modifier            .height(167.dp)
            .background(
                colorResource(R.color.color_f5f5f5),
                shape = RoundedCornerShape(16.dp, 16.dp, 0.dp, 0.dp)
            )


将上例子中的contentScale去掉,并修改imageModifier为如下

val imageModifier = Modifier        .size(150.dp)
        //加了边框
        .border(BorderStroke(1.dp, Black))
        .background(Yellow)
        .clip( RoundedCornerShape(16.dp, 16.dp, 0.dp, 0.dp))


正当我自信满满的时候,代码没有生效!尬住了,仔细查看后,原来是因为默认的缩放属性ContentScale.Fit自适应边界导致的,于是我将缩放属性换为ContentScale.Crop,代码生效了,为了体现效果我去掉了图二的contentScale

代码如下

    val imageModifier = Modifier        .size(150.dp)
        .border(BorderStroke(1.dp, Black))
        .background(Yellow)
        .clip( RoundedCornerShape(16.dp, 16.dp, 0.dp, 0.dp))
    val contentScale =ContentScale.Crop    Row (
        Modifier.background(White),
        horizontalArrangement = Arrangement.Center ,
        verticalAlignment = Alignment.CenterVertically            ){

        Column {
            Image(
                painter = painterResource(id = R.mipmap.girl) ,
                contentDescription = "小姐姐",
                modifier = imageModifier,
                contentScale = contentScale            )
        }
        Column(
            Modifier.padding(start =  10.dp)
        ) {
            Image(
                painter = painterResource(id = R.mipmap.girl1) ,
                contentDescription = "小姐姐1",
                modifier = imageModifier,
            )
        }
    }


效果如下

Compose,Image控件,加载网络图片,contentScale内容缩放

三、为图片加上彩色边框🪁

代码如下

    val rainbowColorsBrush = remember {
        Brush.sweepGradient(
            listOf(
                Color(0xFF9575CD),
                Color(0xFFBA68C8),
                Color(0xFFE57373),
                Color(0xFFFFB74D),
                Color(0xFFFFF176),
                Color(0xFFAED581),
                Color(0xFF4DD0E1),
                Color(0xFF9575CD)
            )
        )
    }
    val imageModifier = Modifier        .size(150.dp)
        .border(
            BorderStroke(4.dp, rainbowColorsBrush),
            RoundedCornerShape(16.dp, 16.dp, 0.dp, 0.dp)
        )
        .background(Yellow)
        .clip( RoundedCornerShape(16.dp, 16.dp, 0.dp, 0.dp))
    val contentScale =ContentScale.Crop    Row (
        Modifier.background(White),
        horizontalArrangement = Arrangement.Center ,
        verticalAlignment = Alignment.CenterVertically            ){

        Column {
            Image(
                painter = painterResource(id = R.mipmap.girl) ,
                contentDescription = "小姐姐",
                modifier = imageModifier,
                contentScale = contentScale            )
        }
        Column(
            Modifier.padding(start =  10.dp)
        ) {
            Image(
                painter = painterResource(id = R.mipmap.girl1) ,
                contentDescription = "小姐姐1",
                modifier = imageModifier,
            )
        }
    }


效果如下
Compose,Image控件,加载网络图片,contentScale内容缩放
到了这一步,可以看到边框和背景还有图片,是三种不同的体现,可以对比差别

四、自定义图片缩放比例🎉

修改imageModifier 代码如下

 val imageModifier = Modifier        .size(150.dp)
        .border(
            BorderStroke(4.dp, rainbowColorsBrush),
            RoundedCornerShape(16.dp, 16.dp, 0.dp, 0.dp)
        )
        .background(Yellow)
        .clip( RoundedCornerShape(16.dp, 16.dp, 0.dp, 0.dp))
        //图片转换为自定义宽高比
        .aspectRatio(16f / 9f)


效果如下
Compose,Image控件,加载网络图片,contentScale内容缩放


五、颜色滤镜 - 转换图片的像素颜色👮‍♂️

1、对图片进行色调调节

这一功能主要是通过colorFilter 方法实现,colorFilter 的基本用法,引用官方示例如下

Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = stringResource(id = R.string.dog_content_description),
    colorFilter = ColorFilter.tint(Color.Green, blendMode = BlendMode.Darken))


可以看到主要是ColorFilter.tint()方法,我们看看它的源码
Compose,Image控件,加载网络图片,contentScale内容缩放
可以看到需要我们传入一个Color颜色,然后传入一个BlendMode(颜色混合的模式【自己的理解】),默认是BlendMode.SrcIn,我们通过官方文档可以看到有如下表格那么多种模式:

混合模式参数效果
BlendMode.Color获取源图像的色调和饱和度,以及目标图像的亮度。
BlendMode.ColorBurn将目标的倒数除以源,然后求结果的倒数。
BlendMode.ColorDodge将目标的倒数除以源。
BlendMode.Darken通过从每个颜色通道中选择最低值来合成源图像和目标图像。
BlendMode.Difference从每个通道的较大值中减去较小值。
BlendMode.Dst删除源图像,仅绘制目标图像。
BlendMode.DstAtop在源图像上合成目标图像,但仅在其与源图像重叠的位置。
BlendMode.DstIn显示目标图像,但仅显示两个图像重叠的位置。
BlendMode.DstOut显示目标图像,但仅在两个图像不重叠的地方显示。
BlendMode.DstOver在目标图像下合成源图像
BlendMode.Exclusion从两幅图像的总和中减去两幅图像乘积的两倍。
BlendMode.Hardlight在调整源图像和目标图像的分量以利于源图像之后,将它们相乘。
BlendMode.Hue获取源图像的色调,以及目标图像的饱和度和亮度。
BlendMode.Lighten通过从每个颜色通道中选择最高值来合成源图像和目标图像。
BlendMode.Luminosity获取源图像的亮度,以及目标图像的色调和饱和度。
BlendMode.Modulate将源图像和目标图像的颜色分量相乘。
BlendMode.Multiply将源图像和目标图像的分量相乘,包括alpha通道。
BlendMode.Overlay在调整源图像和目标图像的分量以有利于目标之后,将它们相乘。
BlendMode.Plus将源图像和目标图像的分量相加。
BlendMode.Saturation获取源图像的饱和度以及目标图像的色调和亮度。
BlendMode.Screen将源图像和目标图像的分量的倒数相乘,并求出结果的倒数。
BlendMode.Softlight对于低于0.5的源值,使用ColorDodge;对于高于0.5的源,使用ColorBurn。
BlendMode.Src删除目标图像,仅绘制源图像。
BlendMode.SrcAtop在目标图像上合成源图像,但仅在其与目标重叠的位置。
BlendMode.SrcIn显示源图像,但仅显示两个图像重叠的位置。
BlendMode.SrcOut显示源图像,但仅在两个图像不重叠的地方显示。
BlendMode.SrcOver在目标图像上合成源图像。
BlendMode.Xor对源图像和目标图像应用逐位异或运算符。

读者可以根据自己的需求选用参数

2、通过颜色矩阵应用图片滤镜

使用如下代码为图片添加黑白滤镜

colorFilter = ColorFilter.colorMatrix(ColorMatrix().apply { setToSaturation(0f) })


效果如下
Compose,Image控件,加载网络图片,contentScale内容缩放
更改对比度或亮度

    val rainbowColorsBrush = remember {
        Brush.sweepGradient(
            listOf(
                Color(0xFF9575CD),
                Color(0xFFBA68C8),
                Color(0xFFE57373),
                Color(0xFFFFB74D),
                Color(0xFFFFF176),
                Color(0xFFAED581),
                Color(0xFF4DD0E1),
                Color(0xFF9575CD)
            )
        )
    }
    val imageModifier = Modifier        .size(150.dp)
        .border(
            BorderStroke(4.dp, rainbowColorsBrush),
            RoundedCornerShape(16.dp, 16.dp, 0.dp, 0.dp)
        )
        .background(Yellow)
        .clip( RoundedCornerShape(16.dp, 16.dp, 0.dp, 0.dp))
        .aspectRatio(16f / 9f)
    val contentScale =ContentScale.Crop    val contrast = 2f // 0f..10f (1 should be default)
    val brightness = -180f // -255f..255f (0 should be default)
    val colorMatrix = floatArrayOf(
        contrast, 0f, 0f, 0f, brightness,
        0f, contrast, 0f, 0f, brightness,
        0f, 0f, contrast, 0f, brightness,
        0f, 0f, 0f, 1f, 0f
    )

    Row (
        Modifier.background(White),
        horizontalArrangement = Arrangement.Center ,
        verticalAlignment = Alignment.CenterVertically            ){

        Column {
            Image(
                painter = painterResource(id = R.mipmap.girl) ,
                contentDescription = "小姐姐",
                modifier = imageModifier,
                contentScale = contentScale,
                //更改对比度或亮度
                colorFilter = ColorFilter.colorMatrix(ColorMatrix(colorMatrix))

            )
        }
        Column(
            Modifier.padding(start =  10.dp)
        ) {
            Image(
                painter = painterResource(id = R.mipmap.girl1) ,
                contentDescription = "小姐姐1",
                modifier = imageModifier,
            )
        }
    }


效果如下

Compose,Image控件,加载网络图片,contentScale内容缩放

模糊效果

更改 imageModifier 代码如下

val imageModifier = Modifier        .size(150.dp)
        .border(
            BorderStroke(4.dp, rainbowColorsBrush),
            RoundedCornerShape(16.dp, 16.dp, 0.dp, 0.dp)
        )
        .background(Yellow)
        .clip( RoundedCornerShape(16.dp, 16.dp, 0.dp, 0.dp))
        .aspectRatio(16f / 9f)
        //模糊效果
        .blur(
            radiusX = 10.dp,
            radiusY = 10.dp,
            edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp))
        )


效果如下

Compose,Image控件,加载网络图片,contentScale内容缩放


完整的代码

    val rainbowColorsBrush = remember {
        Brush.sweepGradient(
            listOf(
                Color(0xFF9575CD),
                Color(0xFFBA68C8),
                Color(0xFFE57373),
                Color(0xFFFFB74D),
                Color(0xFFFFF176),
                Color(0xFFAED581),
                Color(0xFF4DD0E1),
                Color(0xFF9575CD)
            )
        )
    }
    val imageModifier = Modifier        .size(150.dp)
        .border(
            BorderStroke(4.dp, rainbowColorsBrush),
            RoundedCornerShape(16.dp, 16.dp, 0.dp, 0.dp)
        )
        .background(Yellow)
        .clip( RoundedCornerShape(16.dp, 16.dp, 0.dp, 0.dp))
        .aspectRatio(16f / 9f)
        .blur(
            radiusX = 10.dp,
            radiusY = 10.dp,
            edgeTreatment = BlurredEdgeTreatment(RoundedCornerShape(8.dp))
        )
    val contentScale =ContentScale.Crop    val contrast = 2f // 0f..10f (1 should be default)
    val brightness = -180f // -255f..255f (0 should be default)
    val colorMatrix = floatArrayOf(
        contrast, 0f, 0f, 0f, brightness,
        0f, contrast, 0f, 0f, brightness,
        0f, 0f, contrast, 0f, brightness,
        0f, 0f, 0f, 1f, 0f
    )

    Row (
        Modifier.background(White),
        horizontalArrangement = Arrangement.Center ,
        verticalAlignment = Alignment.CenterVertically            ){

        Column {
            Image(
                painter = painterResource(id = R.mipmap.girl) ,
                contentDescription = "小姐姐",
                modifier = imageModifier,
                contentScale = contentScale,
                colorFilter = ColorFilter.colorMatrix(ColorMatrix(colorMatrix))

            )
        }
        Column(
            Modifier.padding(start =  10.dp)
        ) {
            Image(
                painter = painterResource(id = R.mipmap.girl1) ,
                contentDescription = "小姐姐1",
                modifier = imageModifier,
            )
        }
    }


六、加载网络图片👮‍♀️

添加依赖

implementation "io.coil-kt:coil-compose:2.1.0"


使用

@Composablefun NetworkImage(){
    val url = "https://img-blog.yssmx.com/6343e1698dc34686b87dbf50f4eaf0f2.png"
    Column(
        Modifier.padding(top = 50.dp)
    ){
        AsyncImage(
            model = url,
            contentDescription = null
        )



        val modelBuilder = ImageRequest.Builder(LocalContext.current)
            .data(url ?: "")
            .crossfade(false)
            .allowHardware(true)
            .build()

        Image(
            painter = rememberAsyncImagePainter(
                model = modelBuilder            ),
            contentDescription = "头像",
        )
    }}


url为加载网络图片的地址,上例代码为coil对compose加载网络图片的两种方法,效果如下

Compose,Image控件,加载网络图片,contentScale内容缩放
参考Coil对compose加载网络库的支持文章来源地址https://www.toymoban.com/news/detail-500376.html

到了这里,关于Compose布局之Image控件使用详解:加载网络图片与内容缩放的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 小程序使用Image对象预加载图片·获取图片信息

    微信和支付宝等小程序目前都没有直接调用Image的接口, 但可以借用canvas曲线救国,在页面设置个不可见的canvas,再通过canvas的接口能力就能调用到image了 微信案例 支付宝案例 微信小程序开发文档·canvas 支付宝小程序开发文档·canvas

    2024年02月06日
    浏览(27)
  • compose--初入compose、资源获取、标准控件与布局

    compose正式发布已经一年多了,越来越多的开发人员选择使用它, 声明式UI 也是未来的一个主流趋势,本人也是一年前学习后,并没有真正的使用,所以本着边学习,边分享的心态,准备写个compose系列的文章 首先compose目前只支持 kotlin ,基于google对移动端的鸿图,未来应该也

    2024年02月09日
    浏览(33)
  • flutter-使用extended_image操作图片的加载和状态处理

    在 Flutter 的开发过程中,经常会遇到图片的显示和加载处理,通常显示一个图片,都有很多细节需要处理,比如图片的加载、缓存、错误处理、图片的压缩、图片的格式转换等,如果每个地方都手动处理,就太麻烦了,这时候就可以使用糖果大佬的插件 extended_image,它是官方

    2024年02月21日
    浏览(28)
  • [渲染层网络层错误] Failed to load local image resource /miniprogram/images/1.jpg无法加载本地图片资源

    最近开始学习编写小程序,跟着教程走到展示图片这一步发现这个错误。按照正常的编程思路和百度大法,大部分说是路径错误和图片不能带有中字。但是按照经验复制相对路径和绝对路径都不行,还是同样的错误。代码如下。 图片的路径绝对没问题,百度有的博客说用wx

    2024年02月11日
    浏览(35)
  • Android Compose 新闻App(三)网络数据Compose UI显示加载、Room和DataStore使用

    正文 =============================================================== 后面的内容涉及到样式布局组件,内容比较多。 一、样式 在这里我们先进行样式的配置,打开ui.theme文件夹。 首先是修改Color.kt文件 val Blue200 = Color(0xFF979FF2) val Blue300 = Color(0xFF6D7DEA) val Blue700 = Color(0xFF0068C2) val Blue800 = Col

    2024年04月09日
    浏览(61)
  • QML Image 通过 QQuickAsyncImageProvider 异步加载图片

    相关:QML Image 通过 QQuickImageProvider 加载图片-CSDN博客 根据 QQuickImageProvider 的文档说明,该类其实是支持在独立线程中异步加载的,但是 Async 类提供了专用于异步加载的接口,操作起来也不复杂,对于大文件或者网络文件,都可以采用异步方式加载图片。 继续 QQuickAsyncImag

    2024年01月19日
    浏览(34)
  • 合宙Air724UG LuatOS-Air LVGL API控件-图片 (Image)

    图片 (Image) 图片 IMG 是用于显示图像的基本对象类型,图像来源可以是文件,或者定义的符号。 使用  lvgl.img_create  可以创建图像对象。 图片控件显示的内容有两个来源,一个是来源文件的图片,还是有一个就是 符号文字。符号文字是一段特殊的字符串,LVGL内部会将这串特

    2024年02月09日
    浏览(31)
  • 【Flutter】Flutter 图片缓存入门:cached_network_image 解决图片加载的问题

    在这里,我们将一起探讨 Flutter 中的一个非常实用的库——cached_network_image。如果你是一位 Flutter 开发者ÿ

    2024年02月14日
    浏览(31)
  • uni-app image加载错误 404 替换为默认图片

    使用item修改 aitem.cat_icon || defaultPic 绑定图片src属性为aitem.cat_icon 如果aitem.cat_icon的值为空字符串或undefined,那么默认图片defaultPic被显示出来 当图片加载错误时,触发handleImageError方法,将aitem传进去 修改该条数据的cat_icon值 打印aitem如下,修改cat_icon即可 使用index下标修改 当图片

    2024年02月16日
    浏览(31)
  • WPF中手写地图控件(3)——动态加载地图图片

    可以查看我的另一个博客WPF中自定义Loading图 进行从里到外的扩散,方向是上左下右。如下图所示 于是我们可以定义一个拥有坐标X跟Y的集合,他允许这个集合,内部使用枚举器的MoveNext自动排序,中心的在前,外面在后。

    2024年02月11日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包