compose-placeholder icon indicating copy to clipboard operation
compose-placeholder copied to clipboard

Shimer animation does not occur on all items

Open ArleyPereira opened this issue 8 months ago • 9 comments

Hello! First of all, congratulations on the project.

I'm testing the implementation in my multiplatform compose project and I noticed that the shimer animation doesn't occur on all items using LazyRow or Lazycolumn.

Is there anything I can do to make the animation appear on all items?

version: 1.0.10 compose-multiplatform = "1.8.0-rc01"

fun Modifier.shimmerPlaceholder(
    visible: Boolean = false,
    color: Color = Color(0xFFede8ee),
    shape: RoundedCornerShape = RoundedCornerShape(4.dp),
    highlightColor: Color = Color.White,
    animationDurationMillis: Int = 1000
): Modifier {
    return this.placeholder(
        visible = visible,
        color = color,
        shape = shape,
        highlight = PlaceholderHighlight.shimmer(
            highlightColor = highlightColor,
            animationSpec = infiniteRepeatable(
                animation = tween(durationMillis = animationDurationMillis),
                repeatMode = RepeatMode.Restart
            )
        )
    )
}

LazyColumn(
    modifier = Modifier
        .fillMaxSize()
        .padding(horizontal = 16.dp),
    contentPadding = PaddingValues(
        bottom = paddingValues.calculateBottomPadding()
    ),
    verticalArrangement = Arrangement.spacedBy(16.dp)
) {
    items(state.courses) {
        VerticalCourseItemUI(
            course = it,
            isLoadingEffect = state.isLoading,
            onClick = { navigateToCourseDetailsScreen(it.id ?: 0) }
        )
    }
}

https://github.com/user-attachments/assets/86a83ad3-e5b9-4632-8b53-d545df34594c

ArleyPereira avatar Apr 28 '25 13:04 ArleyPereira

Where are you using Modifier.shimmerPlaceholder?

eygraber avatar Apr 28 '25 13:04 eygraber

In some parts of my VerticalCourseItemUI component

@Composable
fun VerticalCourseItemUI(
    modifier: Modifier = Modifier,
    course: Course,
    isLoadingEffect: Boolean = false,
    colors: CardColors = CardDefaults.cardColors(
        containerColor = MyTheme.colorScheme.screen.backgroundSecondary
    ),
    onClick: () -> Unit
) {
    Card(
        onClick = onClick,
        modifier = modifier
            .fillMaxWidth(),
        shape = RoundedCornerShape(12.dp),
        colors = colors,
        border = borderStrokeDefault(),
        content = {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
            ) {
                ImageUI(
                    modifier = Modifier
                        .size(80.dp)
                        .padding(
                            start = 16.dp,
                            top = 16.dp
                        )
                        .shimmerPlaceholder(
                            visible = isLoadingEffect,
                            shape = RoundedCornerShape(12)
                        ),
                    imageModel = course.cover,
                    contentScale = ContentScale.Crop,
                    shape = RoundedCornerShape(12),
                    onClick = onClick
                )

                Column(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(16.dp),
                    verticalArrangement = Arrangement.SpaceBetween
                ) {
                    Text(
                        text = course.title ?: "",
                        modifier = Modifier
                            .shimmerPlaceholder(visible = isLoadingEffect),
                        style = TextStyle(
                            lineHeight = 20.sp,
                            fontFamily = UrbanistFamily(),
                            fontWeight = FontWeight(700),
                            color = MyTheme.colorScheme.text.primaryColor
                        ),
                        maxLines = 2,
                        overflow = TextOverflow.Ellipsis
                    )

                    VerticalSpacer(size = 8)

                    Text(
                        text = course.subtitle ?: "",
                        modifier = Modifier
                            .shimmerPlaceholder(visible = isLoadingEffect),
                        style = TextStyle(
                            fontSize = 12.sp,
                            fontFamily = UrbanistFamily(),
                            color = Greyscale500Color
                        ),
                        maxLines = 2,
                        overflow = TextOverflow.Ellipsis
                    )

                    VerticalSpacer(size = 12)

                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .shimmerPlaceholder(visible = isLoadingEffect),
                        verticalAlignment = Alignment.CenterVertically,
                        horizontalArrangement = Arrangement.End
                    ) {
                        Text(
                            text = DecimalFormat.format(
                                value = 289.9f
                            ),
                            style = TextStyle(
                                fontSize = 12.sp,
                                fontFamily = UrbanistFamily(),
                                color = Greyscale500Color,
                                letterSpacing = 0.2.sp,
                                textDecoration = TextDecoration.LineThrough
                            )
                        )

                        HorizontalSpacer(size = 8)

                        Text(
                            text = DecimalFormat.format(
                                value = course.price
                            ),
                            style = TextStyle(
                                fontSize = 20.sp,
                                lineHeight = 25.2.sp,
                                fontFamily = UrbanistFamily(),
                                fontWeight = FontWeight(700),
                                color = MyTheme.colorScheme.defaultColor,
                                letterSpacing = 0.2.sp
                            )
                        )
                    }

                    VerticalSpacer(size = 12)

                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .shimmerPlaceholder(visible = isLoadingEffect),
                        verticalAlignment = Alignment.CenterVertically,
                        horizontalArrangement = Arrangement.SpaceBetween
                    ) {
                        Row(
                            verticalAlignment = Alignment.CenterVertically,
                            horizontalArrangement = Arrangement.spacedBy(8.dp)
                        ) {
                            Icon(
                                painter = getDrawableIllustration(type = IllustrationType.IC_STAR_LINE),
                                contentDescription = null,
                                modifier = Modifier
                                    .size(16.dp),
                                tint = MyTheme.colorScheme.icon.default
                            )
                            Text(
                                text = "5.0",
                                style = TextStyle(
                                    fontSize = 12.sp,
                                    lineHeight = 22.4.sp,
                                    fontFamily = UrbanistFamily(),
                                    fontWeight = FontWeight(500),
                                    color = MyTheme.colorScheme.icon.default,
                                    letterSpacing = 0.2.sp
                                )
                            )
                        }

                        Row(
                            verticalAlignment = Alignment.CenterVertically,
                            horizontalArrangement = Arrangement.spacedBy(8.dp)
                        ) {
                            Icon(
                                painter = getDrawableIllustration(type = IllustrationType.IC_USERS_LINE),
                                contentDescription = null,
                                modifier = Modifier
                                    .size(16.dp),
                                tint = MyTheme.colorScheme.icon.default
                            )

                            Text(
                                text = "10.598",
                                style = TextStyle(
                                    fontSize = 12.sp,
                                    lineHeight = 22.4.sp,
                                    fontFamily = UrbanistFamily(),
                                    fontWeight = FontWeight(500),
                                    color = MyTheme.colorScheme.icon.default,
                                    letterSpacing = 0.2.sp
                                )
                            )
                        }

                        Row(
                            verticalAlignment = Alignment.CenterVertically,
                            horizontalArrangement = Arrangement.spacedBy(8.dp)
                        ) {
                            Icon(
                                painter = getDrawableIllustration(type = IllustrationType.IC_TIME_LINE),
                                contentDescription = null,
                                modifier = Modifier
                                    .size(16.dp),
                                tint = MyTheme.colorScheme.icon.default
                            )
                            Text(
                                text = "102h",
                                style = TextStyle(
                                    fontSize = 12.sp,
                                    lineHeight = 22.4.sp,
                                    fontFamily = UrbanistFamily(),
                                    fontWeight = FontWeight(500),
                                    color = MyTheme.colorScheme.icon.default,
                                    letterSpacing = 0.2.sp
                                )
                            )
                        }
                    }
                }
            }
        }
    )
}

Image

ArleyPereira avatar Apr 28 '25 14:04 ArleyPereira

Looks like it should work.

Can you try using the placeholder modifier directly, and let me know if that works?

eygraber avatar Apr 28 '25 14:04 eygraber

using only modifier.placeholder also occurs

import com.eygraber.compose.placeholder.PlaceholderHighlight
import com.eygraber.compose.placeholder.material.placeholder
import com.eygraber.compose.placeholder.material.shimmer

@Composable
fun VerticalCourseItemUI(
    modifier: Modifier = Modifier,
    course: Course,
    isLoadingEffect: Boolean = false,
    colors: CardColors = CardDefaults.cardColors(
        containerColor = MyTheme.colorScheme.screen.backgroundSecondary
    ),
    onClick: () -> Unit
) {
    Card(
        onClick = onClick,
        modifier = modifier
            .fillMaxWidth(),
        shape = RoundedCornerShape(12.dp),
        colors = colors,
        border = borderStrokeDefault(),
        content = {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
            ) {
                ImageUI(
                    modifier = Modifier
                        .size(80.dp)
                        .padding(
                            start = 16.dp,
                            top = 16.dp
                        )
                        .placeholder(
                            visible = isLoadingEffect,
                            shape = RoundedCornerShape(12),
                            highlight = PlaceholderHighlight.shimmer()
                        ),
                    imageModel = course.cover,
                    contentScale = ContentScale.Crop,
                    previewPlaceholder = painterResource(Res.drawable.course_example_image),
                    shape = RoundedCornerShape(12),
                    onClick = onClick
                )

                Column(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(16.dp),
                    verticalArrangement = Arrangement.SpaceBetween
                ) {
                    Text(
                        text = course.title ?: "",
                        modifier = Modifier
                            .placeholder(
                                visible = isLoadingEffect,
                                highlight = PlaceholderHighlight.shimmer()
                            ),
                        style = TextStyle(
                            lineHeight = 20.sp,
                            fontFamily = UrbanistFamily(),
                            fontWeight = FontWeight(700),
                            color = MyTheme.colorScheme.text.primaryColor
                        ),
                        maxLines = 2,
                        overflow = TextOverflow.Ellipsis
                    )

                    VerticalSpacer(size = 8)

                    Text(
                        text = course.subtitle ?: "",
                        modifier = Modifier
                            .placeholder(
                                visible = isLoadingEffect,
                                highlight = PlaceholderHighlight.shimmer()
                            ),
                        style = TextStyle(
                            fontSize = 12.sp,
                            fontFamily = UrbanistFamily(),
                            color = Greyscale500Color
                        ),
                        maxLines = 2,
                        overflow = TextOverflow.Ellipsis
                    )

                    VerticalSpacer(size = 12)

                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .placeholder(
                                visible = isLoadingEffect,
                                highlight = PlaceholderHighlight.shimmer()
                            ),
                        verticalAlignment = Alignment.CenterVertically,
                        horizontalArrangement = Arrangement.End
                    ) {
                        Text(
                            text = DecimalFormat.format(
                                value = 289.9f
                            ),
                            style = TextStyle(
                                fontSize = 12.sp,
                                fontFamily = UrbanistFamily(),
                                color = Greyscale500Color,
                                letterSpacing = 0.2.sp,
                                textDecoration = TextDecoration.LineThrough
                            )
                        )

                        HorizontalSpacer(size = 8)

                        Text(
                            text = DecimalFormat.format(
                                value = course.price
                            ),
                            style = TextStyle(
                                fontSize = 20.sp,
                                lineHeight = 25.2.sp,
                                fontFamily = UrbanistFamily(),
                                fontWeight = FontWeight(700),
                                color = MyTheme.colorScheme.defaultColor,
                                letterSpacing = 0.2.sp
                            )
                        )
                    }

                    VerticalSpacer(size = 12)

                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .placeholder(
                                visible = isLoadingEffect,
                                highlight = PlaceholderHighlight.shimmer()
                            ),
                        verticalAlignment = Alignment.CenterVertically,
                        horizontalArrangement = Arrangement.SpaceBetween
                    ) {
                        Row(
                            verticalAlignment = Alignment.CenterVertically,
                            horizontalArrangement = Arrangement.spacedBy(8.dp)
                        ) {
                            Icon(
                                painter = getDrawableIllustration(type = IllustrationType.IC_STAR_LINE),
                                contentDescription = null,
                                modifier = Modifier
                                    .size(16.dp),
                                tint = MyTheme.colorScheme.icon.default
                            )
                            Text(
                                text = "5.0",
                                style = TextStyle(
                                    fontSize = 12.sp,
                                    lineHeight = 22.4.sp,
                                    fontFamily = UrbanistFamily(),
                                    fontWeight = FontWeight(500),
                                    color = MyTheme.colorScheme.icon.default,
                                    letterSpacing = 0.2.sp
                                )
                            )
                        }

                        Row(
                            verticalAlignment = Alignment.CenterVertically,
                            horizontalArrangement = Arrangement.spacedBy(8.dp)
                        ) {
                            Icon(
                                painter = getDrawableIllustration(type = IllustrationType.IC_USERS_LINE),
                                contentDescription = null,
                                modifier = Modifier
                                    .size(16.dp),
                                tint = MyTheme.colorScheme.icon.default
                            )

                            Text(
                                text = "10.598",
                                style = TextStyle(
                                    fontSize = 12.sp,
                                    lineHeight = 22.4.sp,
                                    fontFamily = UrbanistFamily(),
                                    fontWeight = FontWeight(500),
                                    color = MyTheme.colorScheme.icon.default,
                                    letterSpacing = 0.2.sp
                                )
                            )
                        }

                        Row(
                            verticalAlignment = Alignment.CenterVertically,
                            horizontalArrangement = Arrangement.spacedBy(8.dp)
                        ) {
                            Icon(
                                painter = getDrawableIllustration(type = IllustrationType.IC_TIME_LINE),
                                contentDescription = null,
                                modifier = Modifier
                                    .size(16.dp),
                                tint = MyTheme.colorScheme.icon.default
                            )
                            Text(
                                text = "102h",
                                style = TextStyle(
                                    fontSize = 12.sp,
                                    lineHeight = 22.4.sp,
                                    fontFamily = UrbanistFamily(),
                                    fontWeight = FontWeight(500),
                                    color = MyTheme.colorScheme.icon.default,
                                    letterSpacing = 0.2.sp
                                )
                            )
                        }
                    }
                }
            }
        }
    )
}

https://github.com/user-attachments/assets/4b823ca0-41db-46b3-b449-7b45c9ec73b9

ArleyPereira avatar Apr 28 '25 15:04 ArleyPereira

Ok I will look into it. Thanks for the report.

eygraber avatar Apr 28 '25 15:04 eygraber

It's possible that the issue is the library is still using CMP 1.7.3

Otherwise I'm not sure what could be causing the issue. What KMP target is this happening on?

eygraber avatar Apr 28 '25 16:04 eygraber

compose-multiplatform = "1.8.0-rc01"

ArleyPereira avatar Apr 28 '25 17:04 ArleyPereira

The KMP target, meaning Android, ios, Desktop, etc...

eygraber avatar Apr 28 '25 17:04 eygraber

Android, ios

ArleyPereira avatar Apr 28 '25 17:04 ArleyPereira

Sorry I thought I had responded to this. I released v1.0.11 last month which uses Compose 1.8.0. Can you try with that and see if the issue is resolved?

eygraber avatar Jun 09 '25 16:06 eygraber

I just tested version 1.0.11 and it still happens. It happens when I move quickly in lists

ArleyPereira avatar Jun 11 '25 15:06 ArleyPereira

OK I will take a look again.

eygraber avatar Jun 11 '25 15:06 eygraber

I think https://github.com/eygraber/compose-placeholder/pull/335 might fix this. Can you try the latest SNAPSHOT and let me know if that works?

eygraber avatar Sep 11 '25 18:09 eygraber

Solved. Thank you very much for your help.

ArleyPereira avatar Sep 17 '25 14:09 ArleyPereira