---
title: "InteractionSource"
description: "InteractionSource represents a stream of [Interaction]s corresponding to events emitted by a
component. These [Interaction]s can be used to change how components appear in different states,
such as when a component is pressed or dragged.

A common use case is [androidx.compose.foundation.indication], where
[androidx.compose.foundation.Indication] implementations can subscribe to an [InteractionSource]
to draw indication for different [Interaction]s, such as a ripple effect for
[PressInteraction.Press] and a state overlay for [DragInteraction.Start].

For simple cases where you are interested in the binary state of an [Interaction], such as
whether a component is pressed or not, you can use [InteractionSource.collectIsPressedAsState]
and other extension functions that subscribe and return a [Boolean] [State] representing whether
the component is in this state or not.


For more complex cases, such as when building an [androidx.compose.foundation.Indication], the
order of the events can change how a component / indication should be drawn. For example, if a
component is being dragged and then becomes focused, the most recent [Interaction] is
[FocusInteraction.Focus], so the component should appear in a focused state to signal this event
to the user.

InteractionSource exposes [interactions] to support these use cases - a [Flow] representing the
stream of all emitted [Interaction]s. This also provides more information, such as the press
position of [PressInteraction.Press], so you can show an effect at the specific point the
component was pressed, and whether the press was [PressInteraction.Release] or
[PressInteraction.Cancel], for cases when a component should behave differently if the press was
released normally or interrupted by another gesture.

You can collect from [interactions] as you would with any other [Flow]:


To emit [Interaction]s so that consumers can react to them, see [MutableInteractionSource]."
type: "interface"
---

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


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

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



```kotlin
interface InteractionSource
```


InteractionSource represents a stream of `Interaction`s corresponding to events emitted by a
component. These `Interaction`s can be used to change how components appear in different states,
such as when a component is pressed or dragged.

A common use case is `androidx.compose.foundation.indication`, where
`androidx.compose.foundation.Indication` implementations can subscribe to an `InteractionSource`
to draw indication for different `Interaction`s, such as a ripple effect for
`PressInteraction.Press` and a state overlay for `DragInteraction.Start`.

For simple cases where you are interested in the binary state of an `Interaction`, such as
whether a component is pressed or not, you can use `InteractionSource.collectIsPressedAsState`
and other extension functions that subscribe and return a `Boolean` `State` representing whether
the component is in this state or not.


For more complex cases, such as when building an `androidx.compose.foundation.Indication`, the
order of the events can change how a component / indication should be drawn. For example, if a
component is being dragged and then becomes focused, the most recent `Interaction` is
`FocusInteraction.Focus`, so the component should appear in a focused state to signal this event
to the user.

InteractionSource exposes `interactions` to support these use cases - a `Flow` representing the
stream of all emitted `Interaction`s. This also provides more information, such as the press
position of `PressInteraction.Press`, so you can show an effect at the specific point the
component was pressed, and whether the press was `PressInteraction.Release` or
`PressInteraction.Cancel`, for cases when a component should behave differently if the press was
released normally or interrupted by another gesture.

You can collect from `interactions` as you would with any other `Flow`:


To emit `Interaction`s so that consumers can react to them, see `MutableInteractionSource`.


## Properties

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


```kotlin
val interactions: Flow<Interaction>
```


`Flow` representing the stream of all `Interaction`s emitted through this
`InteractionSource`. This can be used to see `Interaction`s emitted in order, and with
additional metadata, such as the press position for `PressInteraction.Press`.




## Code Examples

### InteractionSourceFlowSample
```kotlin
@Composable
fun InteractionSourceFlowSample() {
    // Hoist the MutableInteractionSource that we will provide to interactions
    val interactionSource = remember { MutableInteractionSource() }
    // Provide the MutableInteractionSource instances to the interactions we want to observe state
    // changes for
    val draggable =
        Modifier.draggable(
            interactionSource = interactionSource,
            orientation = Orientation.Horizontal,
            state = rememberDraggableState { /* update some business state here */ },
        )
    val clickable =
        Modifier.clickable(
            interactionSource = interactionSource,
            // This component is a compound component where part of it is clickable and part of it
            // is
            // draggable. As a result we want to show indication for the _whole_ component, and not
            // just for clickable area. We set `null` indication here and provide an explicit
            // Modifier.indication instance later that will draw indication for the whole component.
            indication = null,
        ) { /* update some business state here */
        }
    // SnapshotStateList we will use to track incoming Interactions in the order they are emitted
    val interactions = remember { mutableStateListOf<Interaction>() }
    // Collect Interactions - if they are new, add them to `interactions`. If they represent stop /
    // cancel events for existing Interactions, remove them from `interactions` so it will only
    // contain currently active `interactions`.
    LaunchedEffect(interactionSource) {
        interactionSource.interactions.collect { interaction ->
            when (interaction) {
                is PressInteraction.Press -> interactions.add(interaction)
                is PressInteraction.Release -> interactions.remove(interaction.press)
                is PressInteraction.Cancel -> interactions.remove(interaction.press)
                is DragInteraction.Start -> interactions.add(interaction)
                is DragInteraction.Stop -> interactions.remove(interaction.start)
                is DragInteraction.Cancel -> interactions.remove(interaction.start)
            }
        }
    }
    // Display some text based on the most recent Interaction stored in `interactions`
    val text =
        when (interactions.lastOrNull()) {
            is DragInteraction.Start -> "Dragged"
            is PressInteraction.Press -> "Pressed"
            else -> "No state"
        }
    Column(Modifier.fillMaxSize().wrapContentSize()) {
        Row(
            // Draw indication for the whole component, based on the Interactions dispatched by
            // our hoisted MutableInteractionSource
            Modifier.indication(
                interactionSource = interactionSource,
                indication = LocalIndication.current,
            )
        ) {
            Box(
                Modifier.size(width = 240.dp, height = 80.dp)
                    .then(clickable)
                    .border(BorderStroke(3.dp, Color.Blue))
                    .padding(3.dp)
            ) {
                val pressed = interactions.any { it is PressInteraction.Press }
                Text(
                    text = if (pressed) "Pressed" else "Not pressed",
                    style = LocalTextStyle.current.copy(textAlign = TextAlign.Center),
                    modifier = Modifier.fillMaxSize().wrapContentSize(),
                )
            }
            Box(
                Modifier.size(width = 240.dp, height = 80.dp)
                    .then(draggable)
                    .border(BorderStroke(3.dp, Color.Red))
                    .padding(3.dp)
            ) {
                val dragged = interactions.any { it is DragInteraction.Start }
                Text(
                    text = if (dragged) "Dragged" else "Not dragged",
                    style = LocalTextStyle.current.copy(textAlign = TextAlign.Center),
                    modifier = Modifier.fillMaxSize().wrapContentSize(),
                )
            }
        }
        Text(
            text = text,
            style = LocalTextStyle.current.copy(textAlign = TextAlign.Center),
            modifier = Modifier.fillMaxSize().wrapContentSize(),
        )
    }
}
```

### SimpleInteractionSourceSample
```kotlin
@Composable
fun SimpleInteractionSourceSample() {
    // Hoist the MutableInteractionSource that we will provide to interactions
    val interactionSource = remember { MutableInteractionSource() }
    // Provide the MutableInteractionSource instances to the interactions we want to observe state
    // changes for
    val draggable =
        Modifier.draggable(
            interactionSource = interactionSource,
            orientation = Orientation.Horizontal,
            state = rememberDraggableState { /* update some business state here */ },
        )
    val clickable =
        Modifier.clickable(
            interactionSource = interactionSource,
            indication = LocalIndication.current,
        ) { /* update some business state here */
        }
    // Observe changes to the binary state for these interactions
    val isDragged by interactionSource.collectIsDraggedAsState()
    val isPressed by interactionSource.collectIsPressedAsState()
    // Use the state to change our UI
    val (text, color) =
        when {
            isDragged && isPressed -> "Dragged and pressed" to Color.Red
            isDragged -> "Dragged" to Color.Green
            isPressed -> "Pressed" to Color.Blue
            // Default / baseline state
            else -> "Drag me horizontally, or press me!" to Color.Black
        }
    Box(Modifier.fillMaxSize().wrapContentSize().size(width = 240.dp, height = 80.dp)) {
        Box(
            Modifier.fillMaxSize()
                .then(clickable)
                .then(draggable)
                .border(BorderStroke(3.dp, color))
                .padding(3.dp)
        ) {
            Text(
                text,
                style = LocalTextStyle.current.copy(textAlign = TextAlign.Center),
                modifier = Modifier.fillMaxSize().wrapContentSize(),
            )
        }
    }
}
```

