I need to show a custom placeholder in Jetpack Compose using Coil, but that placeholder is not a drawable, it is a composable function that I customized. Is it possible to do this with the Coil? This is the code snippet where I use the Coil:
Image(
modifier = Modifier
.size(120.dp)
.align(Alignment.CenterHorizontally),
painter = rememberImagePainter(
data = entry.imageUrl,
builder = {
crossfade(true)
MyPlaceholder(resourceId = R.drawable.ic_video)
},
),
contentDescription = entry.pokemonName
)
This is my custom placeholder compose function:
@Composable
fun MyPlaceholder(@DrawableRes resourceId: Int) {
Surface(
modifier = Modifier.fillMaxSize(),
color = Color(0xFFE0E0E0)
) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Surface(
modifier = Modifier.size(30.dp),
shape = CircleShape,
color = Color.White
) {
Image(
modifier = Modifier
.padding(
PaddingValues(
start = 11.25.dp,
top = 9.25.dp,
end = 9.25.dp,
bottom = 9.25.dp
)
)
.fillMaxSize(),
painter = painterResource(id = resourceId),
contentDescription = null
)
}
}
}
}
My gradle (Coil):
// Coil
implementation 'io.coil-kt:coil-compose:1.4.0'
CodePudding user response:
Coil has no built-in support for composable placeholders.
You can put your composable inside Box
and display the placeholder over Image
depending on the state.
In my example I display it if the state is Loading
or Error
. You can add another view parameter for the Error
case and use Crossfade
instead of AnimatedVisibility
.
Also I add Modifier.matchParentSize()
to the Image
to follow parent size calculated on the modifier parameter. You can't pass modifier parameter directly to Image
, because modifiers like align
only work for direct children, that's why you alway have to pass it to the container view.
@Composable
fun Image(
painter: ImagePainter,
placeholder: @Composable () -> Unit,
contentDescription: String?,
modifier: Modifier = Modifier,
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.Fit,
alpha: Float = DefaultAlpha,
colorFilter: ColorFilter? = null,
) {
Box(modifier) {
Image(
painter = painter,
contentDescription = contentDescription,
alignment = alignment,
contentScale = contentScale,
alpha = alpha,
colorFilter = colorFilter,
modifier = Modifier.matchParentSize()
)
AnimatedVisibility(
visible = when (painter.state) {
is ImagePainter.State.Empty,
is ImagePainter.State.Success,
-> false
is ImagePainter.State.Loading,
is ImagePainter.State.Error,
-> true
}
) {
placeholder()
}
}
}
Usage:
Image(
painter = rememberImagePainter(imageUrl),
placeholder = {
CustomComposableView(...)
},
contentDescription = "...",
modifier = Modifier
...
)