JetpackCompose从入门到实战学习笔记14——Coli的简单使用
1.简介:
Coil 是一个 Android官方出的配合Jetpack的图片加载库,通过 Kotlin 协程的方式加载图片。
优点如下:
- 更快: Coil 在性能上有很多优化,包括内存缓存和磁盘缓存,把缩略图存保存在内存中,循环利用 bitmap,自动暂停和取消图片网络请求等。
- 更轻量级: Coil 只有2000个方法(前提是你的 APP 里面集成了 OkHttp 和 Coroutines),Coil 和 Picasso 的方法数差不多,相比 Glide 和 Fresco 要轻量很多。
- 更容易使用: Coil 的 API 充分利用了 Kotlin 语言的新特性,简化和减少了很多样板代码。
- 更流行: Coil 首选 Kotlin 语言开发并且使用包含 Coroutines, OkHttp, Okio 和 AndroidX Lifecycles 在内最流行的开源库。 Coil 名字的由来:取 Coroutine Image Loader 首字母得来。
2.添加依赖:
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation "androidx.compose.ui:ui:$compose_version"
implementation 'androidx.compose.material3:material3:1.0.1'
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.3.1'
implementation 'androidx.compose.material:material:1.0.0-rc01'
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
debugImplementation "androidx.compose.ui:ui-text:$compose_version"
implementation "io.coil-kt:coil-compose:2.2.2"
implementation "io.coil-kt:coil-svg:2.2.2"
implementation "com.github.skydoves:landscapist-coil:2.0.3"
implementation "com.github.skydoves:landscapist-glide:2.1.0"
implementation "com.github.skydoves:cloudy:0.1.1"
implementation "io.coil-kt:coil-gif:2.3.0"
implementation "com.airbnb.android:lottie-compose:$lottieVersion"
}
3.Coli加载网络图片:
@Preview
@Composable
fun AsyncImageDemo() {
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(ImageUrl.testUrl1)
.crossfade(true)
.build(),
contentDescription = "compose",
placeholder = painterResource(id = R.mipmap.place_holder),
error = painterResource(id = R.mipmap.place_holder),
onSuccess = {
Log.d(TAG, "success")
},
onError = { error ->
Log.d(TAG, "error")
},
onLoading = { loading ->
Log.d(TAG, "loading")
},
modifier = Modifier.clip(CircleShape)
)
}
4.效果预览如下:
5.异步加载图片:
@Preview
@Composable
fun SubcomposeAsyncImageDemo() {
SubcomposeAsyncImage(
model = ImageRequest
.Builder(LocalContext.current)
.data(ImageUrl.testUrl1)
.build(),
contentDescription = "compose_museum"
) {
if (painter.state is AsyncImagePainter.State.Loading || painter.state is AsyncImagePainter.State.Error) {
CircularProgressIndicator()
} else {
SubcomposeAsyncImageContent()
}
}
}
6.效果预览:
7.网络进度加载图片:
@Preview
@Composable
fun AsyncImagePainterDemo() {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
SubcomposeAsyncImage(
model = ImageUrl.testUrl2 ,
loading = { CircularProgressIndicator() },
contentDescription = null,
modifier = Modifier.size(200.dp,600.dp)
)
SubcomposeAsyncImage(
model = ImageUrl.testUrl2 ,
contentDescription = null,
modifier = Modifier.size(200.dp)
) {
val state = painter.state
when(state) {
is AsyncImagePainter.State.Loading -> CircularProgressIndicator()
is AsyncImagePainter.State.Error -> Text("${state.result.throwable}")
is AsyncImagePainter.State.Success -> SubcomposeAsyncImageContent()
is AsyncImagePainter.State.Empty -> Text("Empty")
}
}
}
}
8.效果预览:
9.Coli加载圆形图片:
@Composable
fun circleImageDemo() {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
modifier = Modifier
.fillMaxWidth()
.height(500.dp),
painter = rememberImagePainter(
data = ImageUrl.testUrl1,
builder = {
placeholder(R.mipmap.avatar)
crossfade(true)
transformations(CircleCropTransformation())//圆形图片
}),
contentDescription = "composeCircleDemo"
)
Spacer(modifier = Modifier.width(10.dp))
Text(text = "圆形图片示例")
}
}
10.效果预览:
11.Coli加载圆角图片:
@Preview
@Composable
fun clipImageDemo() {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Image(
modifier = Modifier
.fillMaxWidth()
.padding(20.dp)
.height(400.dp),
painter = rememberImagePainter(
data = ImageUrl.testUrl1,
builder = {
placeholder(R.mipmap.avatar)
crossfade(true)
transformations(RoundedCornersTransformation(30f, 30f, 30f, 30f))
}),
contentDescription = "composeClipDemo"
)
Text(text = "加载圆角图片")
}
}
12.效果预览:
13.Coli加载gif图片:
@Preview
@Composable
fun coliLoadGifDemo() {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
//自己构建图片加载器
val imageLoader = ImageLoader.Builder(LocalContext.current)
.components(fun ComponentRegistry.Builder.() {
if (SDK_INT >= 28) {
add(ImageDecoderDecoder.Factory())
} else {
add(GifDecoder.Factory())
}
}).build()
Image(
modifier = Modifier
.fillMaxWidth()
.height(400.dp)
.padding(20.dp),
painter = rememberImagePainter(
data = ImageUrl.testGif,
imageLoader = imageLoader,
builder = {
placeholder(R.mipmap.avatar)//占位图
crossfade(true)//淡出效果
}),
contentDescription = null
)
Text(text = "加载gif图片")
}
}
14.效果预览:
15.Coli加载svg图片:
@Preview
@Composable
fun CoilSvgDemo() {
//coli加载svg图片,这里的图片格式是由svg转换后,虽然后缀不少.svg
val context = LocalContext.current
val imageLoader = ImageLoader.Builder(context)
.components { add(SvgDecoder.Factory()) }
.crossfade(true)
.build()
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Image(
painter = rememberAsyncImagePainter(
ImageUrl.svgUrl2,
imageLoader = imageLoader,
),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.height(400.dp)
.padding(20.dp)
)
Text(text = "coli加载svg格式图片")
}
}
16.效果预览:
17.Cloudy高斯模糊图片:
Cloudy 是一个专门处理Jectpack Compose中的Blur高斯模糊效果的支持库,它可以向后兼容低版本,由于官方的SDK中的Modifier.blur()
修饰符只能支持运行在Android 12+
的设备上才有效果,所以可以使用该库做兼容支持。
Cloudy 也不属于 Accompanist 库的一部分,是一个三方库,这里只是实现一下效果.
@Preview(showBackground = true)
@Composable
fun ModifierBlurSample() {
Column(
Modifier.padding(15.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
var progress by remember{ mutableStateOf(0f)}
val radius by animateDpAsState(targetValue = (progress * 10f).dp)
Text(
text = "高斯模糊效果示例",
Modifier.blur(
radius = radius,
edgeTreatment = BlurredEdgeTreatment.Unbounded
),
fontSize = 20.sp
)
Image(
painter = painterResource(id = R.mipmap.avatar),
contentDescription = null,
modifier = Modifier
.height(400.dp)
.fillMaxWidth()
.blur(
radius = radius,
edgeTreatment = BlurredEdgeTreatment.Unbounded
),
)
Slider(
value = progress,
onValueChange = { progress = it },
)
}
}
18.效果预览:
这里我是使用自己的Android13版本的手机测试的,发现有很明显的高斯模糊效果,但是在12以下的手机和模拟器上面都没有效果~~
19.设置模糊度效果:
@Preview
@Composable
fun BlurCloudyLibSample() {
Column(
Modifier.padding(15.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
var radius by remember{ mutableStateOf(0)}
// radius支持范围是[0..25]
Cloudy(radius = radius) {
Column {
AsyncImage(
model = ImageUrl.testUrl2,
contentDescription = null,
onSuccess = { radius = 1 },
modifier = Modifier
.fillMaxWidth()
.height(400.dp)
)
Spacer(modifier = Modifier.width(20.dp))
Text(text = "高斯模糊渐变效果测试", fontSize = 30.sp)
}
}
Spacer(modifier = Modifier.width(20.dp))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
Button(onClick = { if (radius > 0) radius-- }) { Text(text = "模糊度减") }
Text(text = "radius: $radius", fontSize = 30.sp)
Button(onClick = { if (radius < 25) radius++ }) { Text(text = "模糊度加") }
}
}
}
20.效果预览:
21.完整代码如下:
package com.example.composemodifiterdemo
import android.content.ContentValues.TAG
import android.os.Build.VERSION.SDK_INT
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Slider
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.BlurredEdgeTreatment
import androidx.compose.ui.draw.blur
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.ComponentRegistry
import coil.ImageLoader
import coil.compose.*
import coil.decode.GifDecoder
import coil.decode.ImageDecoderDecoder
import coil.decode.SvgDecoder
import coil.request.ImageRequest
import coil.transform.CircleCropTransformation
import coil.transform.RoundedCornersTransformation
import com.skydoves.cloudy.Cloudy
import com.skydoves.landscapist.ImageOptions
import com.skydoves.landscapist.coil.CoilImage
/**
*@author: njb
*@date: 2023/3/15 17:56
*@desc:
*/
class ColiSampleActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
//AsyncImageDemo()
// SubComposeAsyncImageDemo()
// AsyncImagePainterDemo()
//circleImageDemo()
//clipImageDemo()
coliLoadGifDemo()
//CoilSvgDemo()
// CoilImageSVGDemo()
//loadBlurSample()
// BlurCloudyLibSample()
}
}
}
@Preview
@Composable
fun AsyncImageDemo() {
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(ImageUrl.testUrl1)
.crossfade(true)
.build(),
contentDescription = "compose",
placeholder = painterResource(id = R.mipmap.place_holder),
error = painterResource(id = R.mipmap.place_holder),
onSuccess = {
Log.d(TAG, "success")
},
modifier = Modifier
.fillMaxWidth()
.height(500.dp)
)
}
@Composable
fun circleImageDemo() {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
modifier = Modifier
.fillMaxWidth()
.height(500.dp),
painter = rememberImagePainter(
data = ImageUrl.testUrl1,
builder = {
placeholder(R.mipmap.avatar)
crossfade(true)
transformations(CircleCropTransformation())//圆形图片
}),
contentDescription = "composeCircleDemo"
)
Spacer(modifier = Modifier.width(10.dp))
Text(text = "圆形图片示例")
}
}
@Preview
@Composable
fun clipImageDemo() {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Image(
modifier = Modifier
.fillMaxWidth()
.padding(20.dp)
.height(400.dp),
painter = rememberImagePainter(
data = ImageUrl.testUrl1,
builder = {
placeholder(R.mipmap.avatar)
crossfade(true)
transformations(RoundedCornersTransformation(30f, 30f, 30f, 30f))
}),
contentDescription = "composeClipDemo"
)
Text(text = "加载圆角图片")
}
}
@Preview
@Composable
fun coliLoadGifDemo() {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
//自己构建图片加载器
val imageLoader = ImageLoader.Builder(LocalContext.current)
.components(fun ComponentRegistry.Builder.() {
if (SDK_INT >= 28) {
add(ImageDecoderDecoder.Factory())
} else {
add(GifDecoder.Factory())
}
}).build()
Image(
modifier = Modifier
.fillMaxWidth()
.height(400.dp)
.padding(20.dp),
painter = rememberImagePainter(
data = ImageUrl.testGif,
imageLoader = imageLoader,
builder = {
placeholder(R.mipmap.avatar)//占位图
crossfade(true)//淡出效果
}),
contentDescription = null
)
Text(text = "加载gif图片")
}
}
@Preview
@Composable
fun SubComposeAsyncImageDemo() {
SubcomposeAsyncImage(
model = ImageRequest
.Builder(LocalContext.current)
.data(ImageUrl.testUrl2)
.build(),
contentDescription = "composeAsyncDemo",
modifier = Modifier
.fillMaxWidth()
.height(500.dp)
) {
if (painter.state is AsyncImagePainter.State.Loading || painter.state is AsyncImagePainter.State.Error) {
CircularProgressIndicator()
} else {
SubcomposeAsyncImageContent()
}
}
Text(text = "composeAsyncDemo")
}
@Preview
@Composable
fun AsyncImagePainterDemo() {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
SubcomposeAsyncImage(
model = ImageUrl.testUrl2,
loading = { CircularProgressIndicator() },
contentDescription = null,
modifier = Modifier.size(200.dp, 600.dp)
)
SubcomposeAsyncImage(
model = ImageUrl.testUrl2,
contentDescription = null,
modifier = Modifier.size(200.dp)
) {
val state = painter.state
when (state) {
is AsyncImagePainter.State.Loading -> CircularProgressIndicator()
is AsyncImagePainter.State.Error -> Text("${state.result.throwable}")
is AsyncImagePainter.State.Success -> SubcomposeAsyncImageContent()
is AsyncImagePainter.State.Empty -> Text("Empty")
}
}
}
}
@Preview
@Composable
fun CoilSvgDemo() {
//coli加载svg图片
val context = LocalContext.current
val imageLoader = ImageLoader.Builder(context)
.components { add(SvgDecoder.Factory()) }
.crossfade(true)
.build()
Image(
painter = rememberAsyncImagePainter(
ImageUrl.svgUrl2,
imageLoader = imageLoader,
),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.height(400.dp)
)
}
@Composable
fun CoilImageSVGDemo() {
// 加载网络svg
val context = LocalContext.current
val imageLoader = ImageLoader.Builder(context)
.components { add(SvgDecoder.Factory()) }
.build()
var flag by remember { mutableStateOf(false) }
val size by animateDpAsState(targetValue = if (flag) 600.dp else 300.dp)
CoilImage(
imageModel = { ImageUrl.svgUrl2 },
imageOptions = ImageOptions(
contentScale = ContentScale.Crop,
alignment = Alignment.Center
),
modifier = Modifier
.size(size)
.clickable(
onClick = { flag = !flag },
indication = null,
interactionSource = MutableInteractionSource()
),
imageLoader = { imageLoader }
)
}
@Preview(showBackground = true)
@Composable
fun loadBlurSample() {
Column(
Modifier.padding(15.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
var progress by remember { mutableStateOf(0f) }
val radius by animateDpAsState(targetValue = (progress * 10f).dp)
Text(
text = "高斯模糊效果示例",
Modifier.blur(
radius = radius,
edgeTreatment = BlurredEdgeTreatment.Unbounded
),
fontSize = 20.sp
)
Image(
painter = painterResource(id = R.mipmap.test_iage),
contentDescription = null,
modifier = Modifier
.height(400.dp)
.fillMaxWidth()
.blur(
radius = radius,
edgeTreatment = BlurredEdgeTreatment.Unbounded
),
)
Slider(
value = progress,
onValueChange = { progress = it },
)
}
}
@Preview
@Composable
fun BlurCloudyLibSample() {
Column(
Modifier.padding(15.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
var radius by remember { mutableStateOf(0) }
// 模糊度支持范围是[0..25]
Cloudy(radius = radius) {
Column {
AsyncImage(
model = ImageUrl.svgUrl2,
contentDescription = null,
onSuccess = { radius = 1 },
modifier = Modifier
.fillMaxWidth()
.height(400.dp)
)
}
}
Text(text = "高斯模糊渐变效果测试", fontSize = 20.sp)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
Button(onClick = { if (radius > 0) radius-- }) { Text(text = "模糊度减") }
Text(text = "模糊度设置: $radius", fontSize = 20.sp)
Button(onClick = { if (radius < 25) radius++ }) { Text(text = "模糊度加") }
}
}
}
class ImageUrl {
companion object {
val url: String by lazy {
"https://qcloudimg-moss.cp47.ott.cibntv.net/data_center/files/2022/10/26/67a66d35-3f7c-4de8-9dfe-c706e42f44f2.jpg"
}
var urlTest: String =
"https://pic-go-bed.oss-cn-beijing.aliyuncs.com/img/20220316151929.png"
var svgUrl: String =
"https://developer.android.google.cn/static/images/jetpack/compose/animation-flowchart.svg"
var svgUrl2 = "https://photo.16pic.com/00/76/45/16pic_7645957_b.png"
var svgUrl3 = "https://photo.16pic.com/00/64/28/16pic_6428912_b.png"
var svgUrl4 =
"https://img0.baidu.com/it/u=480894149,21356393&fm=253&fmt=auto&app=138&f=JPEG?w=786&h=500"
var svgUrl5 =
"https://img1.baidu.com/it/u=4053028698,2643070273&fm=253&fmt=auto&app=138&f=JPEG?w=1200&h=500"
var testUrl =
"https://img0.baidu.com/it/u=450558320,2864057328&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500"
var testUrl1 = "https://image5.cnpp.cn/upload/images/20171114/11542556845_840x560.jpg"
var testUrl2 =
"https://img2.baidu.com/it/u=3107178066,1951512797&fm=253&fmt=auto&app=138&f=JPEG?w=704&h=500"
var testGif = "https://img-blog.csdnimg.cn/b286b49591dc4bbd8578300a6e6cfb8e.gif#pic_center"
}
}
22.总结:
以上就是今天的学习内容,在compose中简单使用coli,希望对大家有帮助,一起学习,共同进步!!