package com.gy.composestudy
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.listSaver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.MeasurePolicy
import androidx.compose.ui.layout.ParentDataModifier
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.dp
import com.gy.composestudy.ui.theme.ComposeStudyTheme
import com.gy.composestudy.view.circle
import kotlinx.coroutines.delay
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ComposeStudyTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Box(modifier = Modifier.fillMaxSize()){
AutoFadeInComposableColumn(
Modifier.fillMaxSize(),
){
Box(modifier = Modifier.fillMaxWidth()
.height(100.dp)
.fadeIn(false)
.background(Color.Yellow)
) {
Text("2")
}
Box(modifier = Modifier.fillMaxWidth()
.height(100.dp)
.fadeIn(true)
.background(Color.Red)
) {
Text("1")
}
Box(modifier = Modifier.fillMaxWidth()
.height(100.dp)
.fadeIn(true)
.background(Color.Red)
) {
Text("1")
}
Box(modifier = Modifier.fillMaxWidth()
.height(100.dp)
.fadeIn(false)
.background(Color.Yellow)
) {
Text("3")
}
}
}
}
}
}
}
}
private const val TAG = "AutoFadeInComposableCol"
@Composable
fun AutoFadeInComposableColumn(
modifier: Modifier = Modifier,
state: AutoFadeInColumnState = rememberAutoFadeInColumnState(),
fadeInTime: Int = 1000,
fadeOffsetY: Int = 100,
content: @Composable FadeInColumnScope.() -> Unit
) {
var whetherFadeIn: List<Boolean> = arrayListOf()
val fadeInAnimatable = remember {
Animatable(0f)
}
LaunchedEffect(state.currentFadeIndex){
while (whetherFadeIn.isEmpty()){ delay(50) }
if (state.currentFadeIndex == -1) {
state.currentFadeIndex = whetherFadeIn.indexOf(true)
}
fadeInAnimatable.animateTo(
targetValue = 1f,
animationSpec = tween(
durationMillis = fadeInTime,
easing = LinearEasing
)
)
state.finishedFadeIndex = state.currentFadeIndex
if(state.finishedFadeIndex >= whetherFadeIn.size - 1) return@LaunchedEffect
for (i in state.finishedFadeIndex + 1 until whetherFadeIn.size){
if (whetherFadeIn[i]){
state.currentFadeIndex = i
fadeInAnimatable.snapTo(0f)
break
}
}
}
val measurePolicy = MeasurePolicy { measurables, constraints ->
val placeables = measurables.map { measurable ->
measurable.measure(constraints.copy(minHeight = 0, minWidth = 0))
}
whetherFadeIn = measurables.map {
((it.parentData as? FadeInColumnData) ?: FadeInColumnData()).fade
}
var y = 0
layout(constraints.maxWidth, placeables.sumOf { it.height }) {
placeables.forEachIndexed { index, placeable ->
y = if (state.currentFadeIndex == index) {
y + (( 1 - fadeInAnimatable.value) * fadeOffsetY).toInt()
} else {
y
}
placeable.placeRelativeWithLayer(0, y){
alpha = if (index == state.currentFadeIndex) fadeInAnimatable.value else
if (index <= state.finishedFadeIndex) 1f else 1f
}
y += placeable.height
}.also {
y = 0
}
}
}
Layout(modifier = modifier, content = { FadeInColumnScopeInstance.content() }, measurePolicy = measurePolicy)
}
class FadeInColumnData(val fade: Boolean = true) : ParentDataModifier {
override fun Density.modifyParentData(parentData: Any?): Any =
this@FadeInColumnData
}
interface FadeInColumnScope {
@Stable
fun Modifier.fadeIn(whetherFadeIn: Boolean = true): Modifier
}
object FadeInColumnScopeInstance : FadeInColumnScope {
override fun Modifier.fadeIn(whetherFadeIn: Boolean): Modifier = this.then(FadeInColumnData(whetherFadeIn))
}
class AutoFadeInColumnState {
var currentFadeIndex by mutableStateOf(-1)
var finishedFadeIndex by mutableStateOf(0)
companion object {
val Saver = listSaver<AutoFadeInColumnState, Int>(
save = { listOf(it.currentFadeIndex, it.finishedFadeIndex) },
restore = {
AutoFadeInColumnState().apply {
currentFadeIndex = it[0]; finishedFadeIndex = it[1]
}
}
)
}
}
@Composable
fun rememberAutoFadeInColumnState(): AutoFadeInColumnState {
return rememberSaveable(saver = AutoFadeInColumnState.Saver) { AutoFadeInColumnState() }
}
原文地址:juejin.cn/post/718693…