Created
November 19, 2021 06:29
-
-
Save ColtonIdle/ad8b60f320136c237166c3fa7cc3fd33 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Composable | |
fun <T> RetainStateCrossfade( | |
targetState: T, | |
modifier: Modifier = Modifier, | |
animationSpec: FiniteAnimationSpec<Float> = tween(), | |
content: @Composable (T) -> Unit | |
) { | |
val items = remember { mutableStateListOf<RetainStateCrossfadeAnimationItem<T>>() } | |
val transitionState = remember { MutableTransitionState(targetState) } | |
val targetChanged = (targetState != transitionState.targetState) | |
transitionState.targetState = targetState | |
val transition = updateTransition(transitionState) | |
if (targetChanged || items.isEmpty()) { | |
// Only manipulate the list when the state is changed, or in the first run. | |
val keys = items.map { it.key }.run { | |
if (!contains(targetState)) { | |
toMutableList().also { it.add(targetState) } | |
} else { | |
this | |
} | |
} | |
items.clear() | |
keys.mapTo(items) { key -> | |
RetainStateCrossfadeAnimationItem(key) { | |
val alpha by transition.animateFloat( | |
transitionSpec = { animationSpec } | |
) { if (it == key) 1f else 0f } | |
Box(Modifier.graphicsLayer { this.alpha = alpha }) { | |
content(key) | |
} | |
} | |
} | |
} else if (transitionState.currentState == transitionState.targetState) { | |
// Remove all the intermediate items from the list once the animation is finished. | |
// items.removeAll { it.key != transitionState.targetState } | |
} | |
Box(modifier) { | |
items.fastForEach { | |
mykey(it.key) { | |
it.content() | |
} | |
} | |
} | |
} | |
@OptIn(ExperimentalContracts::class) | |
inline fun <T> List<T>.fastForEach(action: (T) -> Unit) { | |
contract { callsInPlace(action) } | |
for (index in indices) { | |
val item = get(index) | |
action(item) | |
} | |
} | |
@Composable | |
inline fun <T> mykey( | |
@Suppress("UNUSED_PARAMETER") | |
vararg keys: Any?, | |
block: @Composable () -> T | |
) = block() | |
private data class RetainStateCrossfadeAnimationItem<T>( | |
val key: T, | |
val content: @Composable () -> Unit | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment