Search code examples
androidkotlinandroid-jetpack-composecoil

Coil using jetpack compose


Am trying to load multiple images inside a LazyRow composable , the painter state is always giving me an empty state, i dont know what am missing.

The code of the composable

fun NetworkImage(
    url: String,
    contentDescription: String = "",
    modifier: Modifier,
    alignment: Alignment = Alignment.Center,
    contentScale: ContentScale = ContentScale.Fit,
    alpha: Float = DefaultAlpha,
    colorFilter: ColorFilter? = null,
    placeholderDrawableRes: Int? = null,
    crossFade: Int? = null,
    transformations: List<Transformation>? = null,
    onLoading: @Composable () -> Unit,
    onError: @Composable () -> Unit
) {
    Box(
       modifier = modifier
    ){
        val painter = rememberImagePainter(
            data = url,
            builder = {
                placeholderDrawableRes?.let {
                    placeholder( drawableResId = it )
                }
                error(
                    R.drawable.ic_warning
                )
                crossFade?.let {
                    crossfade(durationMillis = it)
                }
                transformations?.let {
                    transformations(transformations = it)
                }
            }
        )
        val imageState = painter.state

        if(imageState is ImagePainter.State.Loading){
            onLoading()
        }
        if(imageState is ImagePainter.State.Error){
            onError()
        }
        Image(
            painter = painter,
            contentDescription = contentDescription,
            contentScale = contentScale,
            alignment = alignment,
            alpha = alpha,
            colorFilter = colorFilter
        )
    }
 }

Inside The LazyRow

LazyRow(modifier = modifier) {
    items(items = urls){ url ->
        NetworkImage(
            url = url,
            contentScale = ContentScale.Crop,
            modifier = Modifier.fillMaxSize(),
            onLoading = {
                ConstraintLayout(
                    modifier = Modifier.fillMaxSize()
                ) {
                    val indicator = createRef()
                    CircularProgressIndicator(
                        modifier = Modifier.constrainAs(indicator) {
                            top.linkTo(parent.top)
                            bottom.linkTo(parent.bottom)
                            start.linkTo(parent.start)
                            end.linkTo(parent.end)
                        }
                    )
                }
            },
            onError = {
                Icon(
                    painter = painterResource(id = R.drawable.ic_warning),
                    contentDescription = "",
                    tint = Color.Red
                )
            }
        )
    }
}

When i use the NetworkImage Composable only once it works fine , but when i use it inside a loop or a LazyRow , it renders an empty Box. Any hints.


Solution

  • You better use Accompanists Pager (https://google.github.io/accompanist/pager/)

    add Pagers library to app level module

    implementation "com.google.accompanist:accompanist-pager:0.18.0"
    

    Then use this code as a sample

    Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
        val pagerState = rememberPagerState(pageCount = urls.size)
        HorizontalPager(state = pagerState) { index ->
            NetworkImage(
                url = urls[index],
                contentScale = ContentScale.Crop,
                modifier = Modifier
                    .fillMaxWidth()
                    .height(300.dp),
                onLoading = {
                    ConstraintLayout(
                        modifier = Modifier.fillMaxSize()
                    ) {
                        val indicator = createRef()
                        CircularProgressIndicator(
                            modifier = Modifier.constrainAs(indicator) {
                                top.linkTo(parent.top)
                                bottom.linkTo(parent.bottom)
                                start.linkTo(parent.start)
                                end.linkTo(parent.end)
                            }
                        )
                    }
                },
                onError = {
                    Icon(
                        painter = painterResource(id = R.drawable.ic_warning),
                        contentDescription = "",
                        tint = Color.Red
                    )
                }
            )
        }
    }
    

    use NetworkImage composable as it is.