今天我们主要来了解一下Compose的Icon,Image控件,MaterialLoadingImage 以及支持显示网络图片的CoilImage控件。
一:Icon
Icon是显示图标的控件,我们来看看Icon的源码
@Composable
fun Icon(
imageVector: ImageVector,
contentDescription: String?,
modifier: Modifier = Modifier,
tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
) {
...
}
@Composable
fun Icon(
bitmap: ImageBitmap,
contentDescription: String?,
modifier: Modifier = Modifier,
tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
) {
...
}
@Composable
fun Icon(
painter: Painter,
contentDescription: String?,
modifier: Modifier = Modifier,
tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
) {
...
}
可以看到Icon主要是有三种构造器,三种分别是第一个参数不一样。一个是imageVector矢量图,一个是bitmap位图,一个是painter。
- imageVector 矢量图 我们可以通过Icons的方式来添加imageVector
Jetpack Compose 附带 Icons 对象,给我们提供了很多种类型主题的图标。 共有以下五种不同的图标主题:Filled、Outlined、Rounded、TwoTone 和 Sharp。每个主题包含相同的图标,但视觉风格不同。通常,我们应该选择一种主题,并在整个应用中保持使用这一主题,从而确保一致性。 androidx.compose.material这个包下,会为我们依赖一定量的图标进来供我们直接使用,但如需使用其他任何 Material 图标,请将 material-icons-extended 依赖项添加到 build.gradle 文件。@Preview() @Composable fun iconTest(){ Column() { Icon(imageVector = Icons.Filled.Add, contentDescription = "添加") } }
但注意material-icons-extended 是一个大型库,可能会影响您的 APK 大小。因此,请考虑在正式 build 中使用 R8/Proguard 来移除未使用的资源。此外,由于大小较大,您的项目的构建时间和 Android Studio 的预览加载时间在开发过程中也可能会增加。dependencies { ... implementation "androidx.compose.material:material-icons-extended:$compose_version" }
- bitmap 位图,这个相当于我们以前ImageView去设置bitmap是一个道理
@Preview() @Composable fun iconTest(){ Column() { Icon(bitmap = ImageBitmap.imageResource(id = R.drawable.icon_head), contentDescription = "图片Icon") } }
- painter 通过painterResource去引用资源文件。
@Preview() @Composable fun iconTest(){ Column() { Icon(painter = painterResource(id = R.drawable.abc_vector_test), contentDescription = "Icon") } }
- contentDescription 描述信息
- modifier 修饰符 详情可查看该篇文章Jetpack Compose Modifier用法详解
- tint 设置修改图标的颜色。
@Preview() @Composable fun iconTest(){ Column() { Icon(painter = painterResource(id = R.drawable.abc_vector_test), contentDescription = "Icon",tint = Color.Yellow,modifier = Modifier.size(20.dp)) Icon(imageVector = Icons.Filled.Add, contentDescription = "添加",tint = Color.Red,modifier = Modifier.size(20.dp)) Icon(bitmap = ImageBitmap.imageResource(id = R.drawable.icon_add), contentDescription = "图片Icon",tint = Color.Blue,modifier = Modifier.size(20.dp)) } }
二:Image
Image的构造器源码如下
@Composable
fun Image(
painter: Painter,
contentDescription: String?,
modifier: Modifier = Modifier,
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.Fit,
alpha: Float = DefaultAlpha,
colorFilter: ColorFilter? = null
) {
...
}
@Composable
fun Image(
imageVector: ImageVector,
contentDescription: String?,
modifier: Modifier = Modifier,
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.Fit,
alpha: Float = DefaultAlpha,
colorFilter: ColorFilter? = null
)...
@Composable
fun Image(
bitmap: ImageBitmap,
contentDescription: String?,
modifier: Modifier = Modifier,
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.Fit,
alpha: Float = DefaultAlpha,
colorFilter: ColorFilter? = null
) {
...
}
我们看到一样会有painter,imageVector,bitmap
- painter 一样是通过painterResource去设置资源的Id
- imageVector 也可以通过Icons去设置矢量图
- bitmap 设置ImageBitmap
- contentDescription 描述
- modifier 修饰符 详情可查看该篇文章Jetpack Compose Modifier用法详解
@Preview()
@Composable
fun imageTest(){
Column() {
Image(painter = painterResource(id = R.drawable.icon_head), contentDescription = "返回图标",modifier = Modifier.size(20.dp))
Image(imageVector = Icons.Filled.Add, contentDescription = "添加图标",modifier = Modifier.size(20.dp))
Image(bitmap = ImageBitmap.imageResource(id = R.drawable.icon_head), contentDescription = "Bitmap",modifier = Modifier.size(20.dp))
}
}
- contentScale 类似以前ImageView的scaleType属性。去设置ImageView的显示样式
- ContentScale.Crop 居中裁剪 类似ScaleType.centerCrop
- ContentScale.Fit 类似ScaleType.fitCenter
- ContentScale.FillHeight 充满高
- ContentScale.FillWidth 充满宽
- ContentScale.Inside 类似ScaleType.centerInside
- ContentScale.None 不处理
- ContentScale.FillBounds 类似ScaleType.fitXY 拉伸撑满宽高
- alpha 设置透明度
@Preview() @Composable fun imageTest(){ Column() { Image(painter = painterResource(id = R.drawable.icon_head), contentDescription = "返回图标",modifier = Modifier.size(20.dp),contentScale = ContentScale.Crop,alpha = 0.5f) } }
- colorFilter 用于修改在其安装的[Paint]上绘制的每个像素的颜色的效果。 ColorFilter有三种取值方式。
- ColorFilter.tint(color: Color, blendMode: BlendMode = BlendMode.SrcIn)第一个参数的意思是用于混合源内容的颜色,第二个参数 将着色颜色合成到时使用的blendMode。 blenModel有28种取值方式。跟我们以前的Xfermode的PorterDuff.Model类似。
@Preview() @Composable fun imageTest(){ Column() { Image(painter = painterResource(id = R.drawable.icon_head), contentDescription = "返回图标",modifier = Modifier.size(20.dp),contentScale = ContentScale.Crop,alpha = 0.5f,colorFilter = ColorFilter.tint(Color.Red, BlendMode.SrcIn)) } }
- ColorFilter.colorMatrix(colorMatrix: ColorMatrix) 通过传入一个4x5的矩阵去处理
@Preview() @Composable fun imageTest(){ Column() { Image(painter = painterResource(id = R.drawable.icon_head), contentDescription = "返回图标",modifier = Modifier.size(20.dp),contentScale = ContentScale.Crop,alpha = 0.5f,colorFilter = ColorFilter.colorMatrix( ColorMatrix(floatArrayOf(1f,2f,3f,4f,5f,6f,1f,2f,2f,3f,4f,4f,1f,2f,3f,1f,2f,4f,6f,3f)) } }
- ColorFilter.lighting(multiply: Color, add: Color) 创建可用于模拟简单灯光效果的ColorFilter.照明颜色滤光片由两个参数定义,一个用于将光源相乘颜色和一个用于添加到源颜色
@Preview() @Composable fun imageTest(){ Column() { Image(painter = painterResource(id = R.drawable.icon_head), contentDescription = "返回图标",modifier = Modifier.size(20.dp),contentScale = ContentScale.Crop,alpha = 0.5f,colorFilter = ColorFilter.lighting(Color.Red, Color.Blue)) } }
三:CoilImage
CoilImage是google推荐我们去使用的加载网络图片的开源库。项目的github地址accompanist。 使用CoilImage需要在app的build.gradle里面导入如下的包:
implementation "com.google.accompanist:accompanist-coil:0.7.1"
CoilImage的构造代码如下:
@Composable
fun CoilImage(
data: Any,
contentDescription: String?,
modifier: Modifier = Modifier,
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.Fit,
colorFilter: ColorFilter? = null,
fadeIn: Boolean = false,
requestBuilder: (ImageRequest.Builder.(size: IntSize) -> ImageRequest.Builder)? = null,
imageLoader: ImageLoader = CoilImageDefaults.defaultImageLoader(),
@DrawableRes previewPlaceholder: Int = 0,
shouldRefetchOnSizeChange: (currentResult: ImageLoadState, size: IntSize) -> Boolean = DefaultRefetchOnSizeChangeLambda,
onRequestCompleted: (ImageLoadState) -> Unit = EmptyRequestCompleteLambda,
error: @Composable (BoxScope.(ImageLoadState.Error) -> Unit)? = null,
loading: @Composable (BoxScope.() -> Unit)? = null,
) {
...
}
- data 填写网络图片的地址
- contentDescription 描述
- modifier 修饰符 详情可查看该篇文章Jetpack Compose Modifier用法详解
- alignment 对齐方式
Alignment 有如下几种取值
/** * A collection of common [Alignment]s aware of layout direction. */ companion object { // 2D Alignments. @Stable val TopStart: Alignment = BiasAlignment(-1f, -1f) @Stable val TopCenter: Alignment = BiasAlignment(0f, -1f) @Stable val TopEnd: Alignment = BiasAlignment(1f, -1f) @Stable val CenterStart: Alignment = BiasAlignment(-1f, 0f) @Stable val Center: Alignment = BiasAlignment(0f, 0f) @Stable val CenterEnd: Alignment = BiasAlignment(1f, 0f) @Stable val BottomStart: Alignment = BiasAlignment(-1f, 1f) @Stable val BottomCenter: Alignment = BiasAlignment(0f, 1f) @Stable val BottomEnd: Alignment = BiasAlignment(1f, 1f) // 1D Alignment.Verticals. @Stable val Top: Vertical = BiasAlignment.Vertical(-1f) @Stable val CenterVertically: Vertical = BiasAlignment.Vertical(0f) @Stable val Bottom: Vertical = BiasAlignment.Vertical(1f) // 1D Alignment.Horizontals. @Stable val Start: Horizontal = BiasAlignment.Horizontal(-1f) @Stable val CenterHorizontally: Horizontal = BiasAlignment.Horizontal(0f) @Stable val End: Horizontal = BiasAlignment.Horizontal(1f) }
- contentScale 类似以前ImageView的scaleType属性。去设置ImageView的显示样式 上面Image讲过
- colorFilter 跟上面Image一样
- fadeIn 设置加载图片渐入的效果
- imageLoader 图片加载器 默认是CoilImageDefaults.defaultImageLoader
@Preview() @Composable fun imageTest(){ Column() { CoilImage( data = "https://picsum.photos/300/300", contentDescription = "My content description", modifier = Modifier.size(50.dp), fadeIn = true ) } }
- requestBuilder 设置一些配置,比如请求完图片后转换成圆形的图片,比如缩放等
@Preview() @Composable fun imageTest(){ Column() { CoilImage( data = "https://picsum.photos/300/300", contentDescription = "My content description", modifier = Modifier.size(50.dp), fadeIn = true, requestBuilder = { transformations(CircleCropTransformation()) } ) } }
- error 请求出错时候显示的控件,比如我们这里给个默认图
@Preview() @Composable fun imageTest(){ Column() { CoilImage( data = "https://picsum.photos/300/300", contentDescription = "My content description", modifier = Modifier.size(50.dp), fadeIn = true, requestBuilder = { transformations(CircleCropTransformation()) }, error = { Image(painter = painterResource(R.drawable.ic_launcher_foreground),contentDescription = "错误时候的图标") } ) } }
- loading 加载时候显示的控件,比如我们给添加个圆形转圈的loading
@Preview() @Composable fun imageTest(){ Column() { CoilImage( data = "https://picsum.photos/300/300", contentDescription = "My content description", modifier = Modifier.size(50.dp), fadeIn = true, requestBuilder = { transformations(CircleCropTransformation()) }, error = { Image(painter = painterResource(R.drawable.ic_launcher_foreground),contentDescription = "错误时候的图标") }, loading = { Box(Modifier.matchParentSize()) { CircularProgressIndicator(Modifier.align(Alignment.Center)) } } ) } }
- previewPlaceholder 加载前占位的资源Id
@Preview() @Composable fun imageTest(){ Column() { CoilImage( data = "https://picsum.photos/300/300", contentDescription = "My content description", modifier = Modifier.size(50.dp), fadeIn = true, requestBuilder = { transformations(CircleCropTransformation()) }, error = { Image(painter = painterResource(R.drawable.ic_launcher_foreground),contentDescription = "错误时候的图标") }, loading = { Box(Modifier.matchParentSize()) { CircularProgressIndicator(Modifier.align(Alignment.Center)) } }, previewPlaceholder=R.drawable.icon_head ) } }
- shouldRefetchOnSizeChange 是否应该重新定义尺寸变化 有两个参数一个是ImageState,一个是IntSize。回调里需要设置返回值Boolean类型
- onRequestCompleted 请求完成后的回调,有个参数是ImageState。ImageState.Success成功,ImageState.Error是失败,ImageLoadState.Loading 加载,ImageLoadState.Empty
@Preview() @Composable fun imageTest(){ Column() { CoilImage( data = "https://picsum.photos/300/300", contentDescription = "My content description", modifier = Modifier.size(50.dp), fadeIn = true, requestBuilder = { transformations(CircleCropTransformation()) }, error = { Image(painter = painterResource(R.drawable.ic_launcher_foreground),contentDescription = "错误时候的图标") }, loading = { Box(Modifier.matchParentSize()) { CircularProgressIndicator(Modifier.align(Alignment.Center)) } }, previewPlaceholder=R.drawable.icon_head, onRequestCompleted = { when(it){ is ImageLoadState.Success->{ // 成功 } is ImageLoadState.Error->{ // 失败 } is ImageLoadState.Loading->{ // 正在请求 } is ImageLoadState.Empty->{ } } } ) } }
注意使用CoilImage的时候记得添加上网络权限。
<uses-permission android:name="android.permission.INTERNET"/>
四:MaterialLoadingImage
相比于Image,在显示图片的时候可以添加淡入淡出的效果,先来看看MaterialLoadingImage的代码
@Composable
fun MaterialLoadingImage(
painter: Painter,
contentDescription: String?,
modifier: Modifier = Modifier,
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.Fit,
colorFilter: ColorFilter? = null,
fadeInEnabled: Boolean = true,
fadeInDurationMs: Int = DefaultTransitionDuration
){
...
}
- painter 跟Image一致
- contentDescription 描述
- modifier 修饰符
- alignment对齐方式
- contentScale 设置图片显示的规则,跟Image一致
- colorFilter 跟Image一致
- fadeInEnabled 是否渐入渐出
- fadeInDurationMs 渐入渐出的时间 默认是1000毫秒
@Preview()
@Composable
fun materialLoadingImageTest(){
MaterialLoadingImage(
painter = painterResource(id = R.drawable.icon_head),
contentDescription = "描述",
modifier = Modifier.size(50.dp),
contentScale = ContentScale.Crop,
fadeInEnabled = true,
fadeInDurationMs = 2000,
// colorFilter = ColorFilter.lighting(Color.Red, Color.Blue),
alignment = Alignment.Center
)
}