HapeLee 5 месяцев назад
Родитель
Сommit
3215adde42

+ 19 - 2
app/src/main/java/io/legado/app/ui/widget/components/image/cover/BookshelfCover.kt

@@ -3,6 +3,8 @@ package io.legado.app.ui.widget.components.image.cover
 import androidx.compose.animation.AnimatedVisibilityScope
 import androidx.compose.animation.ExperimentalSharedTransitionApi
 import androidx.compose.animation.SharedTransitionScope
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
@@ -50,6 +52,18 @@ fun BookshelfCover(
             sharedCoverKey = sharedCoverKey,
         )
 
+        // 使用 animatedVisibilityScope 的 animateEnterExit 为叠加层添加同步动画
+        val overlayModifier = Modifier.then(
+            if (animatedVisibilityScope != null) {
+                with(animatedVisibilityScope) {
+                    Modifier.animateEnterExit(
+                        enter = fadeIn(),
+                        exit = fadeOut()
+                    )
+                }
+            } else Modifier
+        )
+
         if (!badgeText.isNullOrEmpty()) {
             TextCard(
                 text = badgeText,
@@ -57,7 +71,8 @@ fun BookshelfCover(
                 iconSize = 12.dp,
                 modifier = Modifier
                     .align(Alignment.TopEnd)
-                    .padding(2.dp),
+                    .padding(2.dp)
+                    .then(overlayModifier),
                 cornerRadius = 4.dp,
                 horizontalPadding = 4.dp,
                 verticalPadding = 2.dp
@@ -71,7 +86,8 @@ fun BookshelfCover(
                 contentColor = LegadoTheme.colorScheme.onCardContainer,
                 modifier = Modifier
                     .align(Alignment.BottomStart)
-                    .padding(2.dp),
+                    .padding(2.dp)
+                    .then(overlayModifier),
                 cornerRadius = 4.dp,
                 horizontalPadding = 4.dp,
                 verticalPadding = 2.dp
@@ -85,6 +101,7 @@ fun BookshelfCover(
                     .fillMaxWidth()
                     .padding(horizontal = 4.dp, vertical = 6.dp)
                     .height(3.dp)
+                    .then(overlayModifier)
             )
         }
     }

+ 54 - 57
app/src/main/java/io/legado/app/ui/widget/components/image/cover/CoilBookCover.kt

@@ -81,6 +81,17 @@ fun CoilBookCover(
     Box(
         modifier = modifier
             .aspectRatio(5f / 7f)
+            .then(
+                with(sharedTransitionScope) {
+                    if (this != null && animatedVisibilityScope != null && sharedCoverKey != null) {
+                        Modifier.sharedElement(
+                            sharedContentState = rememberSharedContentState(sharedCoverKey),
+                            animatedVisibilityScope = animatedVisibilityScope,
+                            renderInOverlayDuringTransition = true
+                        )
+                    } else Modifier
+                }
+            )
             .then(
                 if (CoverConfig.coverShowShadow) {
                     Modifier.shadow(4.dp, RoundedCornerShape(4.dp))
@@ -94,67 +105,53 @@ fun CoilBookCover(
             )
             .clip(RoundedCornerShape(4.dp))
     ) {
-        val imageContentModifier = Modifier
-            .fillMaxSize()
-            .then(
-                with(sharedTransitionScope) {
-                    if (this != null && animatedVisibilityScope != null && sharedCoverKey != null) {
-                        Modifier.sharedElement(
-                            sharedContentState = rememberSharedContentState(sharedCoverKey),
-                            animatedVisibilityScope = animatedVisibilityScope,
-                            renderInOverlayDuringTransition = true
-                        )
-                    } else Modifier
-                }
+        if (hasCustomDefault && !isOnlineCoverLoaded) {
+            AsyncImage(
+                model = buildCoverImageRequest(
+                    context = context,
+                    data = randomPath,
+                    sourceOrigin = null,
+                    loadOnlyWifi = false,
+                    crossfade = showLoadingPlaceholder,
+                    memoryCacheKey = randomPath,
+                ),
+                contentDescription = null,
+                imageLoader = koinInject(),
+                contentScale = ContentScale.Crop,
+                modifier = Modifier
+                    .fillMaxSize()
+                    .clip(RoundedCornerShape(4.dp))
             )
+        }
 
-        Box(modifier = imageContentModifier) {
-            if (hasCustomDefault && !isOnlineCoverLoaded) {
-                AsyncImage(
-                    model = buildCoverImageRequest(
-                        context = context,
-                        data = randomPath,
-                        sourceOrigin = null,
-                        loadOnlyWifi = false,
-                        crossfade = showLoadingPlaceholder,
-                    ),
-                    contentDescription = null,
-                    imageLoader = koinInject(),
-                    contentScale = ContentScale.Crop,
-                    modifier = Modifier
-                        .fillMaxSize()
-                        .clip(RoundedCornerShape(4.dp))
-                )
-            }
-
-            if (finalPath != null) {
-                AsyncImage(
-                    model = buildCoverImageRequest(
-                        context = context,
-                        data = finalPath,
-                        sourceOrigin = sourceOrigin,
-                        loadOnlyWifi = CoverConfig.loadCoverOnlyWifi,
-                        crossfade = showLoadingPlaceholder,
-                    ),
-                    contentDescription = null,
-                    imageLoader = koinInject(),
-                    contentScale = ContentScale.Crop,
-                    modifier = Modifier
-                        .fillMaxSize()
-                        .clip(RoundedCornerShape(4.dp)),
-                    onSuccess = {
-                        isOnlineCoverLoaded = true
-                        onLoadFinish?.invoke()
-                    },
-                    onError = {
-                        isOnlineCoverLoaded = false
-                        onLoadFinish?.invoke()
-                    }
-                )
-            } else {
-                LaunchedEffect(Unit) {
+        if (finalPath != null) {
+            AsyncImage(
+                model = buildCoverImageRequest(
+                    context = context,
+                    data = finalPath,
+                    sourceOrigin = sourceOrigin,
+                    loadOnlyWifi = CoverConfig.loadCoverOnlyWifi,
+                    crossfade = showLoadingPlaceholder,
+                    memoryCacheKey = finalPath,
+                ),
+                contentDescription = null,
+                imageLoader = koinInject(),
+                contentScale = ContentScale.Crop,
+                modifier = Modifier
+                    .fillMaxSize()
+                    .clip(RoundedCornerShape(4.dp)),
+                onSuccess = {
+                    isOnlineCoverLoaded = true
+                    onLoadFinish?.invoke()
+                },
+                onError = {
+                    isOnlineCoverLoaded = false
                     onLoadFinish?.invoke()
                 }
+            )
+        } else {
+            LaunchedEffect(Unit) {
+                onLoadFinish?.invoke()
             }
         }
 

+ 7 - 0
app/src/main/java/io/legado/app/ui/widget/components/image/cover/CoverImageRequest.kt

@@ -9,11 +9,18 @@ fun buildCoverImageRequest(
     sourceOrigin: String?,
     loadOnlyWifi: Boolean,
     crossfade: Boolean = true,
+    memoryCacheKey: String? = null,
     configure: ImageRequest.Builder.() -> Unit = {},
 ): ImageRequest {
     return ImageRequest.Builder(context)
         .data(data)
         .crossfade(crossfade)
+        .apply {
+            if (memoryCacheKey != null) {
+                memoryCacheKey(memoryCacheKey)
+                placeholderMemoryCacheKey(memoryCacheKey)
+            }
+        }
         .setParameter("sourceOrigin", sourceOrigin)
         .setParameter("loadOnlyWifi", loadOnlyWifi)
         .apply(configure)