androidandroid-jetpack-composeandroid-jetpackcustom-view

User online indicator in Jetpack Compose


I need to achieve the indicator below which shows that the user is online, and has empty borders between image and actual indicator.

How can I achieve it?

Maybe canva is the key, but I do not know how. Please help me produce the indicator.

enter image description here


Solution

  • If you want to use Canvas instead of workaround of adding white border to image, you can checkout below code:

    import androidx.compose.foundation.Canvas
    import androidx.compose.foundation.Image
    import androidx.compose.foundation.layout.Box
    import androidx.compose.foundation.layout.fillMaxSize
    import androidx.compose.foundation.layout.size
    import androidx.compose.runtime.Composable
    import androidx.compose.ui.Alignment
    import androidx.compose.ui.Modifier
    import androidx.compose.ui.geometry.Offset
    import androidx.compose.ui.geometry.Rect
    import androidx.compose.ui.geometry.Size
    import androidx.compose.ui.graphics.Color
    import androidx.compose.ui.graphics.drawscope.Stroke
    import androidx.compose.ui.layout.ContentScale
    import androidx.compose.ui.res.painterResource
    import androidx.compose.ui.unit.dp
    
    
    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            Canvas(modifier = Modifier.fillMaxSize()) {
                val imageWidth = 50.dp.toPx()
                val radius = imageWidth / 2f
                val overlapAmount = radius / 3f
                val iconSize = overlapAmount * 2f
                val iconCenterX = (size.width / 2f) + (imageWidth / 2f) - overlapAmount
                val iconCenterY = (size.height / 2f) + (imageWidth / 2f) - overlapAmount
                val arcStartAngle = 135f // Start angle for the arc in degrees
                val arcSweepAngle = 180f // Sweep angle for the arc in degrees
                val arcRect = Rect(
                    left = (iconCenterX - iconSize / 2f),
                    top = (iconCenterY - iconSize / 2f),
                    right = (iconCenterX + iconSize / 2f),
                    bottom = (iconCenterY + iconSize / 2f)
                )
                drawCircle(
                    color = Color.Gray,
                    radius = radius,
                    center = Offset(size.width / 2f, size.height / 2f)
                )
                drawArc(
                    color = Color.White,
                    startAngle = arcStartAngle,
                    sweepAngle = arcSweepAngle,
                    useCenter = false,
                    topLeft = arcRect.topLeft,
                    size = Size(arcRect.width, arcRect.height),
                    style = Stroke(width = 10f)
                )
                drawCircle(
                    color = Color.Green,
                    radius = iconSize / 2f,
                    center = Offset(iconCenterX, iconCenterY)
                )
            }
            Image(
                painter = painterResource(id = R.drawable.alerter_ic_notifications), // Replace with your profile image resource
                contentDescription = "Profile Image",
                contentScale = ContentScale.Crop,
                modifier = Modifier
                    .size(20.dp)
                    .align(Alignment.Center)
            )
        }
    

    Here is sample output:

    Profile image using canvas