User online indicator in Jetpack Compose

382 Views Asked by At

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

2

There are 2 best solutions below

0
AudioBubble On BEST ANSWER

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

0
heet kanabar On

you can easily do with border property of modifier to the blue dot and add some dp of border to look like that hope you find this helpful.

Edit:- You can use badge compoable function to make UI something like this here is link

Example:-

@Composable
fun DrawUser(users: List<User>) {
    LazyRow(verticalAlignment = Alignment.CenterVertically) {
        items(users) {
            Box {
                Image(
                    bitmap = it.image.asImageBitmap(),
                    contentDescription = "user",
                    modifier = Modifier.clip(
                        CircleShape
                    )
                )
                Image(
                    painter = painterResource(id = R.drawable.dot),
                    contentDescription = "dot",
                    modifier = Modifier
                        .clip(
                            CircleShape
                        )
                        .border(5.dp, color = Color.Black, shape = CircleShape)
                        .align(Alignment.BottomEnd)
                )
            }
        }
    }
}

data class User(val image: Bitmap)

I have my blog here