androidandroid-jetpack-composecoilasyncimageview

Android compose, Indicator size problem with coil


Recently, I try to migrate to Jetpack compose.

So, I want to show 'card' where has 'indicator' while loading but I can't change 'indicator' size in 'SubcomposeAsyncImage'

@Composable
private fun SponsorDialogContent(
    imgUrl: String,
) {
    Card(
        modifier = Modifier
            .width(300.dp)
            .wrapContentHeight(),
        elevation = CardDefaults.cardElevation(0.dp),
        shape = RoundedCornerShape(10.dp)
    ) {
        Box() {
            SubcomposeAsyncImage(
                modifier = Modifier
                    .fillMaxWidth()
                    .wrapContentHeight()
                    .heightIn(min = 200.dp),
                model = imgUrl,
                contentDescription = null,
                loading = {
                    CircularProgressIndicator(modifier = Modifier.size(30.dp).align(Alignment.Center), progress = 1f)
                },
                alignment = Alignment.Center,
                contentScale = ContentScale.FillWidth
            )

            CircularProgressIndicator(1f, Modifier.width(30.dp).align(Alignment.Center))
        }
    }
}

So. I have try the code below

@Composable
private fun SponsorDialogContent(
    imgUrl: String,
) {
    Card(
        modifier = Modifier
            .width(300.dp)
            .wrapContentHeight(),
        elevation = CardDefaults.cardElevation(0.dp),
        shape = RoundedCornerShape(10.dp)
    ) {
        Box() {
            SubcomposeAsyncImage(
                modifier = Modifier
                    .fillMaxWidth()
                    .wrapContentHeight()
                    .heightIn(min = 200.dp),
                model = imgUrl,
                contentDescription = null,
                loading = {
                    Box(contentAlignment = Alignment.Center) {
                        CircularProgressIndicator()
                    }
                },
                alignment = Alignment.Center,
                contentScale = ContentScale.FillWidth
            )
        }
    }
}

Then, works well, but I don't know why Does anyone know why?

I tried to find how to work this code but failed

enter image description here


Solution

  • As @Jan Bina mentioned it has propagateMinConstraints = true which means it forces minimum constraints to its direct child only. I explained in this answer how it effects with Surface because Surface is a Box with propagateMinConstraints = true. You can try out these with Box and you will see the same outcomes

    Surface(
        modifier = Modifier.size(200.dp),
        onClick = {}) {
        Column(
            modifier = Modifier
                .size(50.dp)
                .background(Color.Red, RoundedCornerShape(6.dp))
        ) {}
    }
    
    Spacer(modifier = Modifier.height(20.dp))
    
    Surface(
        modifier = Modifier.size(200.dp),
        onClick = {}) {
        Column(
            modifier = Modifier
                .size(50.dp)
                .background(Color.Red, RoundedCornerShape(6.dp))
        ) {
            Column(
                modifier = Modifier
                    .size(50.dp)
                    .background(Color.Green, RoundedCornerShape(6.dp))
            ) {}
    
        }
    }
    
    Spacer(modifier = Modifier.height(20.dp))
    
    Box(
        modifier = Modifier.size(200.dp)
    ) {
        Column(
            modifier = Modifier
                .size(50.dp)
                .background(Color.Red, RoundedCornerShape(6.dp))
        ) {
            Column(
                modifier = Modifier
                    .size(50.dp)
                    .background(Color.Green, RoundedCornerShape(6.dp))
            ) {}
    
        }
    }
    

    enter image description here

    In first example on Surface forces Column to have 200.dp size even though it has Modifier.size(50.dp).

    In second example Box inside Column has 50.dp size because it's not a direct descendant of Surface.

    In third example if we replace Surface(Box with propagateMinConstraints true) with Box it allows direct descendant to use its own constraints or dimensions.

    And when you set Modifier.fillMaxWidth you set Constraints as minWidth = parent width, maxWidth = parentWidth

    I answered about Constraint types here

    enter image description here