skydoves / landscapist

🌻 A pluggable, highly optimized Jetpack Compose and Kotlin Multiplatform image loading library that fetches and displays network images with Glide, Coil, and Fresco.
https://skydoves.github.io/landscapist/
Apache License 2.0
2.15k stars 114 forks source link

How to crossfade between two images without being empty between transitions? #524

Closed Kerubel-Abera closed 2 months ago

Kerubel-Abera commented 2 months ago

How can I make my image crossfade between a list of images without it disappearing for a second? the animation is working but the it fades from image -> background -> image instead of image -> image

heres my code:

@Composable
fun CrossfadeImages(
    modifier: Modifier = Modifier,
    imageUrls: List<String>,
    durationFadeMillis: Int = 500,
    durationImageMillis: Int = 500,
) {
    var currentImageIndex by remember { mutableStateOf(0) }

    LaunchedEffect(Unit) {
        while (true) {
            delay(durationImageMillis.toLong())
            currentImageIndex = (currentImageIndex + 1) % imageUrls.size
        }
    }

    Crossfade(targetState = imageUrls[currentImageIndex], animationSpec = tween(durationFadeMillis)) { url ->
        CoilImage(
            modifier = modifier,
            component = rememberImageComponent {
                +ShimmerPlugin(
                    Shimmer.Flash(
                        baseColor = BackgroundColor,
                        highlightColor = MainTextColor
                    )
                )
            },
            imageModel = { url },
            imageOptions = ImageOptions(contentScale = ContentScale.Crop)
        )
    }
}
skydoves commented 2 months ago

Hey @Kerubel-Abera, you can achieve this easily with the AnimatedContent with proper duration like the code below:

@Composable
fun CrossfadeImages(
  modifier: Modifier = Modifier,
  imageUrls: List<Poster>,
  durationFadeMillis: Int = 500,
  durationImageMillis: Int = 1000,
) {
  var currentImageIndex by remember { mutableStateOf(0) }

  LaunchedEffect(Unit) {
    while (true) {
      delay(durationImageMillis.toLong())
      currentImageIndex = (currentImageIndex + 1) % imageUrls.size
    }
  }

  AnimatedContent(
    targetState = imageUrls[currentImageIndex].image,
    modifier = modifier,
    transitionSpec = {
      (fadeIn(animationSpec = tween(durationFadeMillis, delayMillis = 0)))
        .togetherWith(fadeOut(animationSpec = tween(durationFadeMillis, delayMillis = 0)))
    }
  ) { state ->
    CoilImage(
      modifier = Modifier.fillMaxSize(),
      imageModel = { state },
      imageOptions = ImageOptions(contentScale = ContentScale.Crop),
    )
  }
}

The result:

2024-08-03 09 48 04