# Animatable

Artifact: [androidx.compose.animation:animation-core](https://developer.android.com/jetpack/androidx/releases/compose-animation) [View Source](https://cs.android.com/search?q=file:androidx/compose/animation/core/Animatable.kt+class:androidx.compose.animation.core.Animatable) Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0) Common/All
- Cmn

  ```
  class Animatable<T : Any?, V : AnimationVector>
  ```

*** ** * ** ***

`https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable` is a value holder that automatically animates its value when the value is changed via `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)`. If `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)` is invoked during an ongoing value change animation, a new animation will transition `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable` from its current value (i.e. value at the point of interruption) to the new `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#targetValue()`. This ensures that the value change is **always** continuous using `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)`. If a `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/package-summary#spring(kotlin.Float,kotlin.Float,kotlin.Any)` animation (e.g. default animation) is used with `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)`, the velocity change will guarantee to be continuous as well.

Unlike `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationState`, `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable` ensures *mutual exclusiveness* on its animations. To achieve this, when a new animation is started via `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)` (or `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)`), any ongoing animation will be canceled via a `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html`.

```kotlin
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.VectorConverter
import androidx.compose.animation.core.spring
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp

// Creates an `Animatable` to animate Offset and `remember` it.
val animatedOffset = remember { Animatable(Offset(0f, 0f), Offset.VectorConverter) }

Box(
    Modifier.fillMaxSize().background(Color(0xffb99aff)).pointerInput(Unit) {
        coroutineScope {
            while (true) {
                val offset = awaitPointerEventScope { awaitFirstDown().position }
                // Launch a new coroutine for animation so the touch detection thread is not
                // blocked.
                launch {
                    // Animates to the pressed position, with the given animation spec.
                    animatedOffset.animateTo(
                        offset,
                        animationSpec = spring(stiffness = Spring.StiffnessLow),
                    )
                }
            }
        }
    }
) {
    Text("Tap anywhere", Modifier.align(Alignment.Center))
    Box(
        Modifier.offset {
                // Use the animated offset as the offset of the Box.
                IntOffset(
                    animatedOffset.value.x.roundToInt(),
                    animatedOffset.value.y.roundToInt(),
                )
            }
            .size(40.dp)
            .background(Color(0xff3c1361), CircleShape)
    )
}
```

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)` |   |

## Summary

| ### Public constructors |
|---|---|
| `@https://developer.android.com/reference/kotlin/androidx/compose/runtime/annotation/RememberInComposition <T : https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-any/index.html?, V : https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationVector> https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#Animatable(kotlin.Any,androidx.compose.animation.core.TwoWayConverter,kotlin.Any,kotlin.String)( initialValue: T, typeConverter: https://developer.android.com/reference/kotlin/androidx/compose/animation/core/TwoWayConverter<T, V>, visibilityThreshold: T?, label: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/index.html )` | Cmn |

| ### Public functions |
|---|---|---|
| `suspend https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationResult<T, V>` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)( initialVelocity: T, animationSpec: https://developer.android.com/reference/kotlin/androidx/compose/animation/core/DecayAnimationSpec<T>, block: (https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable<T, V>.() -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)? )` Start a decay animation (i.e. an animation that *slows down* from the given `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)` starting at current `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()` until the velocity reaches 0. | Cmn |
| `suspend https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationResult<T, V>` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)( targetValue: T, animationSpec: https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationSpec<T>, initialVelocity: T, block: (https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable<T, V>.() -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)? )` Starts an animation to animate from `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()` to the provided `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)`. | Cmn |
| `https://developer.android.com/reference/kotlin/androidx/compose/runtime/State<T>` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#asState()()` Returns a `https://developer.android.com/reference/kotlin/androidx/compose/runtime/State` representing the current `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()` of this animation. | Cmn |
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#snapTo(kotlin.Any)(targetValue: T)` Sets the current value to the target value, without any animation. | Cmn |
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#stop()()` Stops any on-going animation with a `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html`. | Cmn |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#updateBounds(kotlin.Any,kotlin.Any)(lowerBound: T?, upperBound: T?)` Updates either `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#updateBounds(kotlin.Any,kotlin.Any)` or `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#updateBounds(kotlin.Any,kotlin.Any)`, or both. | Cmn |

| ### Public properties |
|---|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#isRunning()` Indicates whether the animation is running. | Cmn |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#label()` An optional label for differentiating this animation from others in android studio. | Cmn |
| `T?` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#lowerBound()` Lower bound of the animation, null by default (meaning no lower bound). | Cmn |
| `T` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#targetValue()` The target of the current animation. | Cmn |
| `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/TwoWayConverter<T, V>` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#typeConverter()` A two-way converter that converts the given type `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable` from and to `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationVector` | Cmn |
| `T?` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#upperBound()` Upper bound of the animation, null by default (meaning no upper bound). | Cmn |
| `T` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()` Current value of the animation. | Cmn |
| `T` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#velocity()` Returns the velocity, converted from `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#velocityVector()`. | Cmn |
| `V` | `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#velocityVector()` Velocity vector of the animation (in the form of `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationVector`. | Cmn |

## Public constructors

### Animatable

Cmn

```
@RememberInComposition
<T : Any?, V : AnimationVector> Animatable(
    initialValue: T,
    typeConverter: TwoWayConverter<T, V>,
    visibilityThreshold: T? = null,
    label: String = "Animatable"
)
```

| Parameters |
|---|---|
| `initialValue: T` | initial value of the animatable value holder |
| `typeConverter: https://developer.android.com/reference/kotlin/androidx/compose/animation/core/TwoWayConverter<T, V>` | A two-way converter that converts the given type `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable` from and to `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationVector` |
| `visibilityThreshold: T? = null` | Threshold at which the animation may round off to its target value. |
| `label: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/index.html = "Animatable"` | An optional label for differentiating this animation from others in android studio. |

## Public functions

### animateDecay

Cmn

```
suspend fun animateDecay(
    initialVelocity: T,
    animationSpec: DecayAnimationSpec<T>,
    block: (Animatable<T, V>.() -> Unit)? = null
): AnimationResult<T, V>
```

Start a decay animation (i.e. an animation that *slows down* from the given `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)` starting at current `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()` until the velocity reaches 0. If there's already an ongoing animation, the animation in-flight will be immediately cancelled. Decay animation is often used after a fling gesture.

`https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)` defines the decay animation that will be used for this animation. Some options for this `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)` include: androidx.compose
.animation.splineBasedDecay and `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/package-summary#exponentialDecay(kotlin.Float,kotlin.Float)`. `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)` will be invoked on each animation frame.

Returns an `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationResult` object, that contains the `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationEndReason` for ending the animation, and an end state of the animation. The reason for ending the animation will be `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationEndReason#Finished` if the animation finishes successfully without any interruption. If the animation reaches the either `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#lowerBound()` or `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#upperBound()` in any dimension, the animation will end with `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationEndReason#BoundReached` being the end reason.

If the animation gets interrupted by 1) another call to start an animation (i.e. `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)`/`https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)`), 2) `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#stop()`, or 3)`https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#snapTo(kotlin.Any)`, the canceled animation will throw a `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html` as the job gets canceled. As a result, all the subsequent work in the caller's coroutine will be canceled. This is often the desired behavior. If there's any cleanup that needs to be done when an animation gets canceled, consider starting the animation in a `try-catch` block.

**Note** , once the animation ends, its velocity will be reset to 0. If there's a need to continue the momentum before the animation gets interrupted or reaches the bound, it's recommended to use the velocity in the returned `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationResult#endState()` to start another animation.

```kotlin
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.calculateTargetValue
import androidx.compose.animation.core.spring
import androidx.compose.animation.splineBasedDecay
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.verticalDrag
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.input.pointer.util.VelocityTracker
import androidx.compose.ui.unit.IntOffset

/**
 * In this example, we create a swipe-to-dismiss modifier that dismisses the child via a
 * vertical swipe-up.
 */
fun Modifier.swipeToDismiss(): Modifier = composed {
    // Creates a Float type `Animatable` and `remember`s it
    val animatedOffsetY = remember { Animatable(0f) }
    this.pointerInput(Unit) {
            coroutineScope {
                while (true) {
                    val pointerId = awaitPointerEventScope { awaitFirstDown().id }
                    val velocityTracker = VelocityTracker()
                    awaitPointerEventScope {
                        verticalDrag(pointerId) {
                            // Snaps the value by the amount of finger movement
                            launch {
                                animatedOffsetY.snapTo(
                                    animatedOffsetY.value + it.positionChange().y
                                )
                            }
                            velocityTracker.addPosition(it.uptimeMillis, it.position)
                        }
                    }
                    // At this point, drag has finished. Now we obtain the velocity at the end
                    // of
                    // the drag, and animate the offset with it as the starting velocity.
                    val velocity = velocityTracker.calculateVelocity().y

                    // The goal for the animation below is to animate the dismissal if the fling
                    // velocity is high enough. Otherwise, spring back.
                    launch {
                        // Checks where the animation will end using decay
                        val decay = splineBasedDecay<Float>(this@pointerInput)

                        // If the animation can naturally end outside of visual bounds, we will
                        // animate with decay.
                        if (
                            decay.calculateTargetValue(animatedOffsetY.value, velocity) <
                                -size.height
                        ) {
                            // (Optionally) updates lower bounds. This stops the animation as
                            // soon
                            // as bounds are reached.
                            animatedOffsetY.updateBounds(lowerBound = -size.height.toFloat())
                            // Animate with the decay animation spec using the fling velocity
                            animatedOffsetY.animateDecay(velocity, decay)
                        } else {
                            // Not enough velocity to be dismissed, spring back to 0f
                            animatedOffsetY.animateTo(0f, initialVelocity = velocity)
                        }
                    }
                }
            }
        }
        .offset { IntOffset(0, animatedOffsetY.value.roundToInt()) }
}
```

### animateTo

Cmn

```
suspend fun animateTo(
    targetValue: T,
    animationSpec: AnimationSpec<T> = defaultSpringSpec,
    initialVelocity: T = velocity,
    block: (Animatable<T, V>.() -> Unit)? = null
): AnimationResult<T, V>
```

Starts an animation to animate from `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()` to the provided `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)`. If there is already an animation in-flight, this method will cancel the ongoing animation before starting a new animation continuing the current `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()` and `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#velocity()`. It's recommended to set the optional `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)` only when `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)` is used immediately after a fling. In most of the other cases, altering velocity would result in visual discontinuity.

The animation will use the provided `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)` to animate the value towards the `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)`. When no `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)` is specified, a `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/package-summary#spring(kotlin.Float,kotlin.Float,kotlin.Any)` will be used. `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)` will be invoked on each animation frame.

Returns an `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationResult` object. It contains: 1) the reason for ending the animation, and 2) an end state of the animation. The reason for ending the animation can be either of the following two:

- `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationEndReason#Finished`, when the animation finishes successfully without any interruption,

- `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationEndReason#BoundReached` If the animation reaches the either `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#lowerBound()` or `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#upperBound()` in any dimension, the animation will end with `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationEndReason#BoundReached` being the end reason.

If the animation gets interrupted by 1) another call to start an animation (i.e. `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)`/`https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)`), 2) `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#stop()`, or 3)`https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#snapTo(kotlin.Any)`, the canceled animation will throw a `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html` as the job gets canceled. As a result, all the subsequent work in the caller's coroutine will be canceled. This is often the desired behavior. If there's any cleanup that needs to be done when an animation gets canceled, consider starting the animation in a `try-catch` block.

**Note** : once the animation ends, its velocity will be reset to 0. The animation state at the point of interruption/reaching bound is captured in the returned `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationResult`. If there's a need to continue the momentum that the animation had before it was interrupted or reached the bound, it's recommended to use the velocity in the returned `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationResult#endState()` to start another animation.

```kotlin
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.graphicsLayer

fun Modifier.fadeIn(): Modifier = composed {
    // Creates an `Animatable` and remembers it.
    val alphaAnimation = remember { Animatable(0f) }
    // Launches a coroutine for the animation when entering the composition.
    // Uses `alphaAnimation` as the subject so the job in `LaunchedEffect` will run only when
    // `alphaAnimation` is created, which happens one time when the modifier enters
    // composition.
    LaunchedEffect(alphaAnimation) {
        // Animates to 1f from 0f for the fade-in, and uses a 500ms tween animation.
        alphaAnimation.animateTo(
            targetValue = 1f,
            // Default animationSpec uses [spring] animation, here we overwrite the default.
            animationSpec = tween(500),
        )
    }
    this.graphicsLayer(alpha = alphaAnimation.value)
}
```

### asState

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0)

```
fun asState(): State<T>
```

Returns a `https://developer.android.com/reference/kotlin/androidx/compose/runtime/State` representing the current `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()` of this animation. This allows hoisting the animation's current value without causing unnecessary recompositions when the value changes.

### snapTo

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0)

```
suspend fun snapTo(targetValue: T): Unit
```

Sets the current value to the target value, without any animation. This will also cancel any on-going animation with a `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html`. This function will return *after* canceling any on-going animation and updating the `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()` and `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#targetValue()` to the provided `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#snapTo(kotlin.Any)`.

**Note** : If the `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#lowerBound()` or `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#upperBound()` is specified, the provided `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#snapTo(kotlin.Any)` will be clamped to the bounds to ensure `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()` is always within bounds.

See `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)` and `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)` for more details about animation being canceled.

| Parameters |
|---|---|
| `targetValue: T` | The new target value to set `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()` to. |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#stop()` |   |

### stop

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0)

```
suspend fun stop(): Unit
```

Stops any on-going animation with a `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-cancellation-exception/index.html`.

This function will not return until the ongoing animation has been canceled (if any). Note, `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#stop()` function does **not** skip the animation value to its target value. Rather the animation will be stopped in its track. Consider `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#snapTo(kotlin.Any)` if it's desired to not only stop the animation but also snap the `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()` to a given value.

See `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)` and `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)` for more details about animation being canceled.

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateTo(kotlin.Any,androidx.compose.animation.core.AnimationSpec,kotlin.Any,kotlin.Function1)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#animateDecay(kotlin.Any,androidx.compose.animation.core.DecayAnimationSpec,kotlin.Function1)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#snapTo(kotlin.Any)` |   |

### updateBounds

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0)

```
fun updateBounds(lowerBound: T? = this.lowerBound, upperBound: T? = this.upperBound): Unit
```

Updates either `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#updateBounds(kotlin.Any,kotlin.Any)` or `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#updateBounds(kotlin.Any,kotlin.Any)`, or both. This will update `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#lowerBound()` and/or `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#upperBound()` accordingly after a check to ensure the provided `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#updateBounds(kotlin.Any,kotlin.Any)` is no greater than `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#updateBounds(kotlin.Any,kotlin.Any)` in any dimension.

Setting the bounds will immediate clamp the `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()`, only if the animation isn't running. For the on-going animation, the value at the next frame update will be checked against the bounds. If the value reaches the bound, then the animation will end with `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationEndReason#BoundReached` end reason.

| Parameters |
|---|---|
| `lowerBound: T? = this.lowerBound` | lower bound of the animation. Defaults to the `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#lowerBound()` that is currently set. |
| `upperBound: T? = this.upperBound` | upper bound of the animation. Defaults to the `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#upperBound()` that is currently set. |

| Throws |
|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-illegal-state-exception/index.html` | if the `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#updateBounds(kotlin.Any,kotlin.Any)` is greater than `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#updateBounds(kotlin.Any,kotlin.Any)` in any dimension. |

## Public properties

### isRunning

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0)

```
val isRunning: Boolean
```

Indicates whether the animation is running.

### label

Cmn Added in [1.3.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.3.0)

```
val label: String
```

An optional label for differentiating this animation from others in android studio.

### lowerBound

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0)

```
val lowerBound: T?
```

Lower bound of the animation, null by default (meaning no lower bound). Bounds can be changed using `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#updateBounds(kotlin.Any,kotlin.Any)`.

Animation will stop as soon as *any* dimension specified in `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#lowerBound()` is reached. For example: For an Animatable with an `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#lowerBound()` set to Offset(100f, 200f), when the `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()`.x drops below 100f *or* `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()`.y drops below 200f, the animation will stop.

### targetValue

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0)

```
val targetValue: T
```

The target of the current animation. If the animation finishes un-interrupted, it will reach this target value.

### typeConverter

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0)

```
val typeConverter: TwoWayConverter<T, V>
```

A two-way converter that converts the given type `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable` from and to `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationVector`

### upperBound

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0)

```
val upperBound: T?
```

Upper bound of the animation, null by default (meaning no upper bound). Bounds can be changed using `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#updateBounds(kotlin.Any,kotlin.Any)`.

Animation will stop as soon as *any* dimension specified in `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#upperBound()` is reached. For example: For an Animatable with an `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#upperBound()` set to Offset(100f, 200f), when the `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()`.x exceeds 100f *or* `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#value()`.y exceeds 200f, the animation will stop.

### value

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0)

```
val value: T
```

Current value of the animation.

### velocity

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0)

```
val velocity: T
```

Returns the velocity, converted from `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/Animatable#velocityVector()`.

### velocityVector

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.0.0)

```
val velocityVector: V
```

Velocity vector of the animation (in the form of `https://developer.android.com/reference/kotlin/androidx/compose/animation/core/AnimationVector`.