原文地址 Jetpack Compose學習(4)——Image(圖片)使用及Coil圖片非同步載入庫使用 | Stars-One的雜貨小窩
本篇講解下關於Image的使用及使用Coil開源庫非同步載入網路圖片顯示
本系列以往文章請檢視此分類連結Jetpack compose學習
Image使用
首先,先看下引數
fun Image(
painter: Painter,
contentDescription: String?,
modifier: Modifier = Modifier,
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.Fit,
alpha: Float = DefaultAlpha,
colorFilter: ColorFilter? = null
)
可以看到Image圖片的引數大體上是和是Icon一樣,基本使用呢,和上一篇講的Icon類似,我們載入一張本地的圖片,程式碼如下
Image(painter = painterResource(id = R.drawable.download),
contentDescription = null
)
比較基礎的引數這裡就不再贅述了,這裡主要講解下面的其他引數
1.alignment
圖片對齊方向,前提是Image設定了寬高,取值為Alignment
的定義的列舉
設定寬高是通過
Modifier.size()
來設定
取值有圖中幾種:
注意: 圖中特意方框圍起來的,其返回值不是
Alignment
型別的,這幾個並不能取,你選了的話編輯器也會貼心的給出錯誤提示的 笑
這個alignment引數有九種取值,將一個固定的長方形分為九塊,如下圖所示
Column() {
//為了便於區分,這裡使用Modifier添加了個黃色的背景
Image(modifier = Modifier.size(200.dp,300.dp).background(color = Color.Yellow),
//圖片自己隨便找張即可
painter = painterResource(id = R.drawable.download),
contentDescription = null,
alignment = Alignment.Center)
}
可以看到實際效果中,圖片是居中對齊的,其他效果也就不一一展示了
2.contentScale
圖片縮放設定,和原生的ImageView的scaleType屬性類似,取值是ContentScale
的列舉,預設是ContentScale.Fit
(即自適應)
ContentScale.Crop
裁剪ContentScale.FillBounds
拉伸圖片寬高填滿形狀ContentScale.FillHeight
拉伸圖片高度填滿高度ContentScale.FillWidth
拉伸圖片寬填滿寬度ContentScale.Fit
ContentScale.Inside
ContentScale.None
不縮放
這個也是需要Image設定寬高才可以看出效果
下面演示各種不同效果的Image(由於Fit是預設的,下面就沒展示出來了)
程式碼如下
Column(Modifier.verticalScroll(rememberScrollState())) {
//為了便於區分,這裡使用Modifier添加了個黃色的背景
Image(modifier = Modifier
.size(200.dp, 150.dp)
.background(color = Color.Yellow),
painter = painterResource(id = R.drawable.download),
contentDescription = null,
contentScale = ContentScale.Crop)
Image(modifier = Modifier
.size(200.dp, 150.dp)
.background(color = Color.Yellow),
painter = painterResource(id = R.drawable.download),
contentDescription = null,
contentScale = ContentScale.Inside)
Image(modifier = Modifier
.size(200.dp, 150.dp)
.background(color = Color.Yellow),
painter = painterResource(id = R.drawable.download),
contentDescription = null,
contentScale = ContentScale.FillBounds)
Image(modifier = Modifier
.size(200.dp, 150.dp)
.background(color = Color.Yellow),
painter = painterResource(id = R.drawable.download),
contentDescription = null,
contentScale = ContentScale.FillHeight)
Image(modifier = Modifier
.size(200.dp, 150.dp)
.background(color = Color.Yellow),
painter = painterResource(id = R.drawable.download),
contentDescription = null,
contentScale = ContentScale.FillWidth)
Image(modifier = Modifier
.size(200.dp, 150.dp)
.background(color = Color.Yellow),
painter = painterResource(id = R.drawable.download),
contentDescription = null,
contentScale = ContentScale.None)
}
3.alpha
透明度,數值型別為float,數值範圍為0f-1f
之間,預設是1f
如下程式碼所示
Image(modifier = Modifier
.size(200.dp, 150.dp)
.background(color = Color.Yellow),
painter = painterResource(id = R.drawable.download),
contentDescription = null,
alpha = 1f
)
Image(modifier = Modifier
.size(200.dp, 150.dp)
.background(color = Color.Yellow),
painter = painterResource(id = R.drawable.download),
contentDescription = null,
alpha = 0.5f)
效果如下圖所示
4.colorFilter
著色效果,可以使用顏色對圖片進行混合加工,有下面三種方法進行設定
ColorFilter.tint(Color, BlendMode)
著色效果ColorFilter.lighting(Color,Color)
ColorFilter.colorMatrix(colorMatrix)
這個我不是研究太多,各位可以百度參考下其他大神寫的文章
這裡就講個小例子,改變圖片的顏色
美工給的圖示有些是單一的顏色,比如說選中後是藍色,不選中是灰色的
但有時候專案需要更改顏色,如選中後要改為綠色,這個時候得要美工再次切圖,十分麻煩
這個時候我們可以這個屬性,去修改顏色,如下面程式碼
Image(modifier = Modifier
.size(200.dp, 150.dp),
painter = painterResource(id = R.drawable.eye_show),
contentDescription = null,
alpha = 1f,
colorFilter = ColorFilter.tint(color = Color.Green, BlendMode.SrcAtop)
)
效果:
R.drawable.eye_show
圖片原本是灰色的,現在被我們渲染成了綠色,這種方法比較適合那種單一顏色的圖示檔案
而且有了這種方法,我們甚至只需要一種灰色的圖示即可,藍色的圖示就不需要,可以省下不少apk的體積大小
至於更多內容,需要各位去研究啦...
Coil圖片非同步載入庫使用
上述我們一直使用的是本地圖片,如果是網路圖片,該怎麼辦呢?以往我們都是使用Glide載入,但現在由於Compose是採用State狀態監測機制去渲染UI,所以如果我們自己去實現就會十分麻煩
剛好現在已經有大神整了框架,我們拿來使用即可
Coil這個框架是Accompanist
的子庫,那麼Accompanist
是什麼呢?
Accompanist 是一組旨在擴充
Jetpack Compose
功能的第三方庫集合,這個庫中所提供的功能是開發者普遍需要的。
注: 寫這篇文章後發現,在Accompanist
的0.16.0
版本更新日誌中,移除了Coil
等圖片載入的庫,Coil
好像是單獨出來了,下面是摘自官方的更新說明:
Coil, Glide and Image Loading Core have been removed
After being deprecated in v0.14.0, it's time to remove the
coil
,glide
andimageloading-core
libraries. Some discussion about this can be seen on the Kotlin Slack: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1627482619344000.TL;DR: the recommendation is to move to Coil Compose.
遷移到此開源庫coil-kt/coil: Image loading for Android backed by Kotlin Coroutines.
基本使用
基本流程,先導依賴
implementation("io.coil-kt:coil:1.3.2")
圖片的painter
引數使用rememberImagePainter
此方法,可傳入一個網路圖片
Image(
painter = rememberImagePainter("https://img0.baidu.com/it/u=312301072,1324966529&fm=26&fmt=auto&gp=0.jpg"),
contentDescription = null,
modifier = Modifier.size(128.dp)
)
PS:不要忘記加網路許可權
<uses-permission android:name="android.permission.INTERNET" />
哦!!
效果:
佔位圖 過渡及圓形裁剪
- 佔位圖 placeholder
- 過渡 transitions
- 變化效果 transformations
由於是網路圖片,我們在預覽介面是無法看到有圖片的,這個時候我們可以考慮設定下佔位圖片,好方便除錯UI
Image(
modifier = Modifier.size(128.dp),
painter = rememberImagePainter(
data = "https://img0.baidu.com/it/u=312301072,1324966529&fm=26&fmt=auto&gp=0.jpg",
builder = {
//佔位圖
placeholder(R.drawable.placeholder)
//淡出效果
crossfade(true)
//圓形效果
transformations(CircleCropTransformation())
}
),
contentDescription = null,
)
預覽介面可以看到佔位圖
載入網路的圖片過渡效果:
可能圖中看不出圓形裁剪,我們可以加上背景看看,圖片其實已經是被裁剪了的
目前,Coil自帶了兩種過渡效果:
CrossfadeTransition
從當前可繪製到成功/錯誤可繪製的淡入淡出(即上文程式碼出現的crossfade
)Transition.NONE
它在Target沒有動畫的情況下立即設定可繪製物件。
想要實現自定義,可以參考下CrossfadeTransition原始碼,本文就不過多展開了
transformations主要是變化的意思,官方的解釋是
transformations允許您在Drawable從請求返回之前修改影象的畫素資料。
Coil預設提供了4種類型 blur
(高斯模糊) circle crop
(圓形裁剪) grayscale
(灰度) rounded corners
(圓角)
對應的程式碼如下:
//radis是外層圓角,sample為高斯模糊的程度(要大於1f即可)
BlurTransformation(context,radius,sample)
//灰度
GrayscaleTransformation()
//圓角
RoundedCornersTransformation(0.8f)
效果如下所示
原始碼:
@ExperimentalCoilApi
@Preview(showBackground = true)
@Composable
fun ImagePageDemo() {
val context = LocalContext.current
ComposeDemoTheme {
Column(Modifier.verticalScroll(rememberScrollState())) {
/*Image(
painter = rememberImagePainter("https://img0.baidu.com/it/u=312301072,1324966529&fm=26&fmt=auto&gp=0.jpg"),
contentDescription = null,
modifier = Modifier.size(128.dp),
)*/
Image(
modifier = Modifier.size(128.dp).background(Color.Blue),
painter = rememberImagePainter(
data = "https://img0.baidu.com/it/u=312301072,1324966529&fm=26&fmt=auto&gp=0.jpg",
builder = {
crossfade(true)
placeholder(R.drawable.placeholder)
transformations(BlurTransformation(context,0.1f,2f))
}
),
contentDescription = null,
)
Image(
modifier = Modifier.size(128.dp).background(Color.Blue),
painter = rememberImagePainter(
data = "https://img0.baidu.com/it/u=312301072,1324966529&fm=26&fmt=auto&gp=0.jpg",
builder = {
crossfade(true)
placeholder(R.drawable.placeholder)
transformations(GrayscaleTransformation())
}
),
contentDescription = null,
)
Image(
modifier = Modifier.size(128.dp).background(Color.Blue),
painter = rememberImagePainter(
data = "https://img0.baidu.com/it/u=312301072,1324966529&fm=26&fmt=auto&gp=0.jpg",
builder = {
crossfade(true)
placeholder(R.drawable.placeholder)
transformations(RoundedCornersTransformation(0.8f))
}
),
contentDescription = null,
)
}
}
}
載入gif
需要新增依賴外掛包
implementation("io.coil-kt:coil-gif:1.3.2")
val context = LocalContext.current
val imageLoader = ImageLoader.Builder(context)
.componentRegistry {
add(GifDecoder())
add(SvgDecoder(context))
}
.build()
Image(
modifier = Modifier.size(128.dp).background(Color.Blue),
painter = rememberImagePainter(
data = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F01bdd05a436090a80121974142c9f3.gif&refer=http%3A%2F%2Fimg.zcool.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1634225053&t=eaa097d38a32f901b7096fae16bfb98f",
builder = {
//加了這個解碼,如果圖片是jpg等格式,是沒法成功解析出來的
decoder(GifDecoder())
crossfade(true)
placeholder(R.drawable.placeholder)
}
),
contentDescription = null,
)
效果如下所示
PS:上述程式碼是我自己大概摸索出來的,沒想到竟然能用...
官方給的文件一直沒有個標準的使用例子,也不知道上面這樣寫對不對,僅供參考
下面這個好像是正確的程式碼,image可以同時支援載入gif或者是jpg等圖片
Column() {
val context = LocalContext.current
//建立圖片載入器
val myImageLoader = ImageLoader.Builder(context)
.componentRegistry {
//這裡可以加多個圖片解碼器
add(GifDecoder())
}
.build()
Image(
modifier = Modifier
.size(128.dp)
.background(Color.Blue),
painter = rememberImagePainter(
data = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.zcool.cn%2Fcommunity%2F01bdd05a436090a80121974142c9f3.gif&refer=http%3A%2F%2Fimg.zcool.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1634225053&t=eaa097d38a32f901b7096fae16bfb98f",
//設定圖片載入器
imageLoader = myImageLoader,
builder = {
crossfade(true)
placeholder(R.drawable.placeholder)
}
),
contentDescription = null,
)
}
載入svg
如gif一樣,也是要加個外掛依賴,之後註冊即可
implementation("io.coil-kt:coil-svg:1.3.2")
val context = LocalContext.current
//建立圖片載入器
val myImageLoader = ImageLoader.Builder(context)
.componentRegistry {
add(GifDecoder())
add(SvgDecoder(context))
}
.build()
補充
下面的都是一樣的,不過使用Coil載入圖片會出現圖片放大後失真問題,所以有另外款開源庫推薦landscapist
implementation "com.github.skydoves:landscapist-coil:1.3.2"
CoilImage(
imageModel = "https://coil-kt.github.io/coil/images/coil_logo_black.svg",
contentDescription = null,
imageLoader = myImageLoader
)
參考
- Jetpack Compose - Image_樂翁龍-CSDN部落格
- Image - Jetpack Compose中文文件
- Accompanist中文翻譯文件 - Jetpack Compose中文文件
- Accompanist官方文件
- Coil官方文件之Jetpack Compose -
- Android-使用 SetColorFilter 神奇地改變圖片的顏色_段淺淺的部落格-CSDN部落格_setcolorfilter