---
title: "SeekableTransitionState"
description: "A [TransitionState] that can manipulate the progress of the [Transition] by seeking with [seekTo]
or animating with [animateTo].

A [SeekableTransitionState] can only be used with one [Transition] instance. Once assigned, it
cannot be reassigned to a different [Transition] instance."
type: "class"
---

<div class='type'>Class</div>


<a id='references'></a>

<div class='sourceset sourceset-common'>Common</div>


```kotlin
public class SeekableTransitionState<S>(initialState: S) : TransitionState<S>()
```


A `TransitionState` that can manipulate the progress of the `Transition` by seeking with `seekTo`
or animating with `animateTo`.

A `SeekableTransitionState` can only be used with one `Transition` instance. Once assigned, it
cannot be reassigned to a different `Transition` instance.


## Functions

```kotlin
public suspend fun snapTo(targetState: S)
```


Sets `currentState` and `targetState` to `targetState` and snaps all values to those at that
state. The transition will not have any animations running after running `snapTo`.

This can have a similar effect as `seekTo`. However, `seekTo` moves the `currentState` to the
former `targetState` and animates the initial values of the animations from the current
values to those at `currentState`. `seekTo` also allows the developer to move the state
between any fraction between `currentState` and `targetState`, while `snapTo` moves all state
to `targetState` without any further seeking allowed.


```kotlin
public suspend fun seekTo(
        @FloatRange(from = 0.0, to = 1.0) fraction: Float,
        targetState: S = this.targetState,
    )
```


Starts seeking the transition to `targetState` with `fraction` used to indicate the progress
towards `targetState`. If the previous `targetState` was already `targetState` then `seekTo`
only stops any current animation towards that state and snaps the fraction to the new value.
Otherwise, the `currentState` is changed to the former `targetState` and `targetState` is
changed to `targetState` and an animation is started, moving the start values towards the
former `targetState`. This will return when the initial values have reached `currentState`
and the `fraction` has been reached.

`snapTo` also allows the developer to change the state, but does not animate any values.
Instead, it instantly moves all values to those at the new `targetState`.


```kotlin
public suspend fun animateTo(
        targetState: S = this.targetState,
        animationSpec: FiniteAnimationSpec<Float>? = null,
    )
```


Updates the current `targetState` to `targetState` and begins an animation to the new state.
If the current `targetState` is the same as `targetState` then the current transition
animation is continued. If a previous transition was interrupted, `currentState` is changed
to the former `targetState` and the start values are animated toward the former
`targetState`.

Upon completion of the animation, `currentState` will be changed to `targetState`.

#### Parameters

| | |
| --- | --- |
| targetState | The state to animate towards. |
| animationSpec | If provided, is used to animate the animation fraction. If `null`, the transition is linearly traversed based on the duration of the transition. |



## Companion Object

#### Properties

<div class='sourceset sourceset-common'>Common</div>


```kotlin
val ZeroVelocity = AnimationVector1D(0f)
```


<div class='sourceset sourceset-common'>Common</div>


```kotlin
val Target1 = AnimationVector1D(1f)
```




## Code Examples

### SeekingAnimationSample
```kotlin
@Composable
fun SeekingAnimationSample() {
    Column {
        val seekingState = remember { SeekableTransitionState(BoxSize.Small) }
        val scope = rememberCoroutineScope()
        Column {
            Row {
                Button(
                    onClick = { scope.launch { seekingState.animateTo(BoxSize.Small) } },
                    Modifier.wrapContentWidth().weight(1f),
                ) {
                    Text("Animate Small")
                }
                Button(
                    onClick = { scope.launch { seekingState.seekTo(0f, BoxSize.Small) } },
                    Modifier.wrapContentWidth().weight(1f),
                ) {
                    Text("Seek Small")
                }
                Button(
                    onClick = { scope.launch { seekingState.seekTo(0f, BoxSize.Medium) } },
                    Modifier.wrapContentWidth().weight(1f),
                ) {
                    Text("Seek Medium")
                }
                Button(
                    onClick = { scope.launch { seekingState.seekTo(0f, BoxSize.Large) } },
                    Modifier.wrapContentWidth().weight(1f),
                ) {
                    Text("Seek Large")
                }
                Button(
                    onClick = { scope.launch { seekingState.animateTo(BoxSize.Large) } },
                    Modifier.wrapContentWidth().weight(1f),
                ) {
                    Text("Animate Large")
                }
            }
        }
        Slider(
            value = seekingState.fraction,
            modifier = Modifier.systemGestureExclusion().padding(10.dp),
            onValueChange = { value -> scope.launch { seekingState.seekTo(fraction = value) } },
        )
        val transition = rememberTransition(seekingState)
        val scale: Float by
            transition.animateFloat(
                transitionSpec = { tween(easing = LinearEasing) },
                label = "Scale",
            ) { state ->
                when (state) {
                    BoxSize.Small -> 1f
                    BoxSize.Medium -> 2f
                    BoxSize.Large -> 3f
                }
            }
        transition.AnimatedContent(
            transitionSpec = {
                fadeIn(tween(easing = LinearEasing)) togetherWith
                    fadeOut(tween(easing = LinearEasing))
            }
        ) { state ->
            if (state == BoxSize.Large) {
                Box(Modifier.size(50.dp).background(Color.Magenta))
            } else {
                Box(Modifier.size(50.dp))
            }
        }
        Box(
            Modifier.fillMaxSize()
                .wrapContentSize(Alignment.Center)
                .size(100.dp)
                .graphicsLayer {
                    scaleX = scale
                    scaleY = scale
                }
                .background(Color.Blue)
        )
    }
}
```

