AnimatedVisibility(
//定义内容是否应该可见
visible = shown,
/*
slideIn、slideInVertically、slideInVertically 只能同时存在一个
enter = slideInVertically(
//从离本身(小于零(上方)大于零(下方))fullHeight位置滑入
initialOffsetY = { fullHeight -> -fullHeight },
animationSpec = tween(durationMillis = 250, easing = FastOutLinearInEasing)
),
enter = slideInHorizontally(
//从离本身(小于零(上方)大于零(下方))fullHeight位置滑入
initialOffsetX = { fullWidth ->-fullWidth },
animationSpec = tween(durationMillis = 2500, easing = LinearOutSlowInEasing)
),
*/
enter = slideIn(
// 从在 initialOffset 中定义的起始偏移量到 IntOffset(0, 0)。
// 滑动的方向可以通过配置initialOffset来控制。
// 正x值表示从右向左滑动,而负x值将向右滑动内容。 同样,正负y值分别对应于向上和向下滑动。
initialOffset = { (fullWidth, fullHeight) ->IntOffset(-fullWidth,-fullHeight) },
// animationSpec配置动画限制
// tween:配置持续时间和缓动曲线的
// repeatable:配置重复的动画(几次,动画,结尾开始或从头开始)
// repeatable(5,tween(durationMillis = 2500, easing = LinearOutSlowInEasing),RepeatMode.Reverse)
// infiniteRepeatable:配置重复的动画(动画,结尾开始或从头开始)
// spring
// durationMillis过渡时间。easing速度处理,默认LinearOutSlowInEasing
// FastOutSlowInEasing:先加速再减速
// LinearOutSlowInEasing:减速
// FastOutLinearInEasing:加速
// LinearEasing:匀速
animationSpec =tween(durationMillis = 2500, easing = LinearOutSlowInEasing)
) + fadeIn(
//不透明度从0.1f 到 1f
initialAlpha = 0.1f,
animationSpec = tween(durationMillis = 2500,easing = LinearEasing)
),
//scaleIn()
exit = slideOutVertically(
// Exits by sliding out from offset 0 to -fullHeight.
targetOffsetY = { fullHeight -> -fullHeight },
animationSpec = tween(durationMillis = 250, easing = FastOutLinearInEasing)
)
) {
......
}
val alpha by infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = keyframes {
durationMillis = 1000
// 添加一个关键帧,以便动画值在时间为:timeStamp。 例如:0.8f at 150 // ms
0.7f at 500
},
repeatMode = RepeatMode.Reverse
)
)
Row(
modifier = Modifier
.heightIn(min = 64.dp)
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Box(
modifier = Modifier
.size(48.dp)
.clip(CircleShape)
.background(Color.LightGray.copy(alpha = alpha))
)
Spacer(modifier = Modifier.width(16.dp))
Box(
modifier = Modifier
.fillMaxWidth()
.height(32.dp)
.background(Color.LightGray.copy(alpha = alpha))
)
}
/**
* The modified element can be horizontally swiped away.
*
* @param onDismissed Called when the element is swiped to the edge of the screen.
*/
private fun Modifier.swipeToDismiss(
onDismissed: () -> Unit
): Modifier = composed {
// This `Animatable` stores the horizontal offset for the element.
val offsetX = remember { Animatable(0f) }
pointerInput(Unit) {
// Used to calculate a settling position of a fling animation.
val decay = splineBasedDecay(this)
// Wrap in a coroutine scope to use suspend functions for touch events and animation.
coroutineScope {
while (true) {
// Wait for a touch down event.
val pointerId = awaitPointerEventScope { awaitFirstDown().id }
// Interrupt any ongoing animation.
offsetX.stop()
// Prepare for drag events and record velocity of a fling.
val velocityTracker = VelocityTracker()
// Wait for drag events.
awaitPointerEventScope {
horizontalDrag(pointerId) { change ->
// Record the position after offset
val horizontalDragOffset = offsetX.value + change.positionChange().x
launch {
// Overwrite the `Animatable` value while the element is dragged.
offsetX.snapTo(horizontalDragOffset)
}
// Record the velocity of the drag.
velocityTracker.addPosition(change.uptimeMillis, change.position)
// Consume the gesture event, not passed to external
change.consumePositionChange()
}
}
// Dragging finished. Calculate the velocity of the fling.
val velocity = velocityTracker.calculateVelocity().x
// Calculate where the element eventually settles after the fling animation.
val targetOffsetX = decay.calculateTargetValue(offsetX.value, velocity)
// The animation should end as soon as it reaches these bounds.
offsetX.updateBounds(
lowerBound = -size.width.toFloat(),
upperBound = size.width.toFloat()
)
launch {
if (targetOffsetX.absoluteValue <= size.width) {
// Not enough velocity; Slide back to the default position.
offsetX.animateTo(targetValue = 0f, initialVelocity = velocity)
} else {
// Enough velocity to slide away the element to the edge.
offsetX.animateDecay(velocity, decay)
// The element was swiped away.
onDismissed()
}
}
}
}
}
// Apply the horizontal offset to the element.
.offset { IntOffset(offsetX.value.roundToInt(), 0) }
}