Add a revered parameter to AvatarRow to be able to stack avatar the other way.

This commit is contained in:
Benoit Marty 2025-08-20 16:26:37 +02:00
parent 333b1c8a48
commit 324fc28e2d

View file

@ -38,6 +38,7 @@ import kotlinx.collections.immutable.toImmutableList
* @param modifier Jetpack Compose modifier * @param modifier Jetpack Compose modifier
* @param overlapRatio the overlap ration. When 0f, avatars will render without overlap, when 1f * @param overlapRatio the overlap ration. When 0f, avatars will render without overlap, when 1f
* only the first avatar will be visible * only the first avatar will be visible
* @param lastOnTop if true, the last visible avatar will be rendered on top.
*/ */
@Composable @Composable
fun AvatarRow( fun AvatarRow(
@ -45,6 +46,7 @@ fun AvatarRow(
avatarType: AvatarType, avatarType: AvatarType,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
overlapRatio: Float = 0.5f, overlapRatio: Float = 0.5f,
lastOnTop: Boolean = false,
) { ) {
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
Box( Box(
@ -54,23 +56,35 @@ fun AvatarRow(
val avatarSize = avatarDataList.firstOrNull()?.size?.dp ?: return val avatarSize = avatarDataList.firstOrNull()?.size?.dp ?: return
val avatarSizePx = avatarSize.toPx() val avatarSizePx = avatarSize.toPx()
avatarDataList avatarDataList
.reversed() .let {
if (lastOnTop) {
it
} else {
it.reversed()
}
}
.forEachIndexed { index, avatarData -> .forEachIndexed { index, avatarData ->
val startPadding = if (lastOnTop) {
avatarSize * (1 - overlapRatio) * index
} else {
avatarSize * (1 - overlapRatio) * (lastItemIndex - index)
}
Avatar( Avatar(
modifier = Modifier modifier = Modifier
.padding(start = avatarSize * (1 - overlapRatio) * (lastItemIndex - index)) .padding(start = startPadding)
.graphicsLayer { .graphicsLayer {
compositingStrategy = CompositingStrategy.Offscreen compositingStrategy = CompositingStrategy.Offscreen
} }
.drawWithContent { .drawWithContent {
// Draw content and clear the pixels for the avatar on the left (right in RTL). // Draw content and clear the pixels for the avatar on the left (right in RTL) or when lastOnTop is true on
// the right (left in RTL).
drawContent() drawContent()
val xOffset = if (isRtl) {
size.width - avatarSizePx * (overlapRatio - 0.5f)
} else {
0f + avatarSizePx * (overlapRatio - 0.5f)
}
if (index < lastItemIndex) { if (index < lastItemIndex) {
val xOffset = if (isRtl == lastOnTop) {
avatarSizePx * (overlapRatio - 0.5f)
} else {
size.width - avatarSizePx * (overlapRatio - 0.5f)
}
drawCircle( drawCircle(
color = Color.Black, color = Color.Black,
center = Offset( center = Offset(
@ -101,6 +115,17 @@ internal fun AvatarRowPreview(@PreviewParameter(OverlapRatioProvider::class) ove
} }
} }
@Composable
@PreviewsDayNight
internal fun AvatarRowLastOnTopPreview(@PreviewParameter(OverlapRatioProvider::class) overlapRatio: Float) {
ElementPreview {
ContentToPreview(
overlapRatio = overlapRatio,
lastOnTop = true,
)
}
}
@Composable @Composable
@PreviewsDayNight @PreviewsDayNight
internal fun AvatarRowRtlPreview(@PreviewParameter(OverlapRatioProvider::class) overlapRatio: Float) { internal fun AvatarRowRtlPreview(@PreviewParameter(OverlapRatioProvider::class) overlapRatio: Float) {
@ -114,7 +139,25 @@ internal fun AvatarRowRtlPreview(@PreviewParameter(OverlapRatioProvider::class)
} }
@Composable @Composable
private fun ContentToPreview(overlapRatio: Float) { @PreviewsDayNight
internal fun AvatarRowLastOnTopRtlPreview(@PreviewParameter(OverlapRatioProvider::class) overlapRatio: Float) {
CompositionLocalProvider(
LocalLayoutDirection provides LayoutDirection.Rtl,
) {
ElementPreview {
ContentToPreview(
overlapRatio = overlapRatio,
lastOnTop = true,
)
}
}
}
@Composable
private fun ContentToPreview(
overlapRatio: Float,
lastOnTop: Boolean = false,
) {
AvatarRow( AvatarRow(
avatarDataList = listOf("A", "B", "C").map { avatarDataList = listOf("A", "B", "C").map {
AvatarData( AvatarData(
@ -125,5 +168,6 @@ private fun ContentToPreview(overlapRatio: Float) {
}.toImmutableList(), }.toImmutableList(),
avatarType = AvatarType.User, avatarType = AvatarType.User,
overlapRatio = overlapRatio, overlapRatio = overlapRatio,
lastOnTop = lastOnTop,
) )
} }