MangaSummary: Refactor to not use SubcomposeLayout (#10008)

This commit is contained in:
Ivan Iskandar 2023-10-14 21:52:04 +07:00 committed by GitHub
parent c492efcb31
commit 0026f96fad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -48,7 +48,6 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
@ -63,9 +62,8 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.SubcomposeLayout import androidx.compose.ui.layout.Layout
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
@ -589,67 +587,70 @@ private fun MangaSummary(
expanded: Boolean, expanded: Boolean,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
var expandedHeight by remember { mutableIntStateOf(0) }
var shrunkHeight by remember { mutableIntStateOf(0) }
val heightDelta = remember(expandedHeight, shrunkHeight) { expandedHeight - shrunkHeight }
val animProgress by animateFloatAsState(if (expanded) 1f else 0f) val animProgress by animateFloatAsState(if (expanded) 1f else 0f)
val scrimHeight = with(LocalDensity.current) { remember { 24.sp.roundToPx() } } Layout(
modifier = modifier.clipToBounds(),
SubcomposeLayout(modifier = modifier.clipToBounds()) { constraints -> contents = listOf(
val shrunkPlaceable = subcompose("description-s") { {
Text(
text = "\n\n", // Shows at least 3 lines
style = MaterialTheme.typography.bodyMedium,
)
}.map { it.measure(constraints) }
shrunkHeight = shrunkPlaceable.maxByOrNull { it.height }?.height ?: 0
val expandedPlaceable = subcompose("description-l") {
Text(
text = expandedDescription,
style = MaterialTheme.typography.bodyMedium,
)
}.map { it.measure(constraints) }
expandedHeight = expandedPlaceable.maxByOrNull { it.height }?.height?.coerceAtLeast(shrunkHeight) ?: 0
val actualPlaceable = subcompose("description") {
SelectionContainer {
Text( Text(
text = if (expanded) expandedDescription else shrunkDescription, text = "\n\n", // Shows at least 3 lines
maxLines = Int.MAX_VALUE,
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.secondaryItemAlpha(),
) )
} },
}.map { it.measure(constraints) } {
Text(
text = expandedDescription,
style = MaterialTheme.typography.bodyMedium,
)
},
{
SelectionContainer {
Text(
text = if (expanded) expandedDescription else shrunkDescription,
maxLines = Int.MAX_VALUE,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.secondaryItemAlpha(),
)
}
},
{
val colors = listOf(Color.Transparent, MaterialTheme.colorScheme.background)
Box(
modifier = Modifier.background(Brush.verticalGradient(colors = colors)),
contentAlignment = Alignment.Center,
) {
val image = AnimatedImageVector.animatedVectorResource(R.drawable.anim_caret_down)
Icon(
painter = rememberAnimatedVectorPainter(image, !expanded),
contentDescription = stringResource(if (expanded) R.string.manga_info_collapse else R.string.manga_info_expand),
tint = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.background(Brush.radialGradient(colors = colors.asReversed())),
)
}
},
),
) { (shrunk, expanded, actual, scrim), constraints ->
val shrunkHeight = shrunk.single()
.measure(constraints)
.height
val expandedHeight = expanded.single()
.measure(constraints)
.height
val heightDelta = expandedHeight - shrunkHeight
val scrimHeight = 24.dp.roundToPx()
val scrimPlaceable = subcompose("scrim") { val actualPlaceable = actual.single()
val colors = listOf(Color.Transparent, MaterialTheme.colorScheme.background) .measure(constraints)
Box( val scrimPlaceable = scrim.single()
modifier = Modifier.background(Brush.verticalGradient(colors = colors)), .measure(Constraints.fixed(width = constraints.maxWidth, height = scrimHeight))
contentAlignment = Alignment.Center,
) {
val image = AnimatedImageVector.animatedVectorResource(R.drawable.anim_caret_down)
Icon(
painter = rememberAnimatedVectorPainter(image, !expanded),
contentDescription = stringResource(if (expanded) R.string.manga_info_collapse else R.string.manga_info_expand),
tint = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.background(Brush.radialGradient(colors = colors.asReversed())),
)
}
}.map { it.measure(Constraints.fixed(width = constraints.maxWidth, height = scrimHeight)) }
val currentHeight = shrunkHeight + ((heightDelta + scrimHeight) * animProgress).roundToInt() val currentHeight = shrunkHeight + ((heightDelta + scrimHeight) * animProgress).roundToInt()
layout(constraints.maxWidth, currentHeight) { layout(constraints.maxWidth, currentHeight) {
actualPlaceable.forEach { actualPlaceable.place(0, 0)
it.place(0, 0)
}
val scrimY = currentHeight - scrimHeight val scrimY = currentHeight - scrimHeight
scrimPlaceable.forEach { scrimPlaceable.place(0, scrimY)
it.place(0, scrimY)
}
} }
} }
} }