androidx.compose.foundation.content

Interfaces

ReceiveContentListener

A set of callbacks for contentReceiver modifier to get information about certain Drag-and-Drop state changes, as well as receiving the payload carrying TransferableContent.

Cmn

Classes

MediaType

Type identifier for contents that are transferable between applications or processes.

Cmn
android
PlatformTransferableContent

All the platform-specific information regarding a TransferableContent that cannot be abstracted away in a platform agnostic way.

Cmn
android
TransferableContent

Represents content that can be transferred between applications or processes.

Cmn
TransferableContent.Source

Defines the type of operation that a TransferableContent originates from.

Cmn

Extension functions summary

TransferableContent?

Helper function to consume parts of TransferableContent in Android by splitting it to ClipData.Item parts.

android
Modifier

Configures the current node and any children nodes as a Content Receiver.

Cmn
Boolean

Returns whether this TransferableContent can provide an item with the mediaType.

Cmn
android

Extension functions

@ExperimentalFoundationApi
fun TransferableContent.consume(predicate: (ClipData.Item) -> Boolean): TransferableContent?

Helper function to consume parts of TransferableContent in Android by splitting it to ClipData.Item parts. Use this function in contentReceiver modifier's onReceive callback to easily separate remaining parts from incoming TransferableContent.

import androidx.compose.foundation.Image
import androidx.compose.foundation.content.MediaType
import androidx.compose.foundation.content.consume
import androidx.compose.foundation.content.contentReceiver
import androidx.compose.foundation.content.hasMediaType
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap

val state = rememberTextFieldState()
var images by remember { mutableStateOf<List<ImageBitmap>>(emptyList()) }
Column {
    Row { images.forEach { Image(bitmap = it, contentDescription = null) } }
    BasicTextField(
        state = state,
        modifier =
            Modifier.contentReceiver { transferableContent ->
                if (!transferableContent.hasMediaType(MediaType.Image)) {
                    return@contentReceiver transferableContent
                }
                val newImages = mutableListOf<ImageBitmap>()
                transferableContent
                    .consume { item ->
                        // only consume this item if we can read an imageBitmap
                        item.readImageBitmap()?.let {
                            newImages += it
                            true
                        } ?: false
                    }
                    .also { images = newImages }
            }
    )
}
Parameters
predicate: (ClipData.Item) -> Boolean

Decides whether to consume or leave the given item out. Return true to indicate that this particular item was processed here, it shouldn't be passed further down the content receiver chain. Return false to keep it in the returned TransferableContent.

Returns
TransferableContent?

Remaining parts of this TransferableContent.

contentReceiver

@ExperimentalFoundationApi
fun Modifier.contentReceiver(
    receiveContentListener: ReceiveContentListener
): Modifier

Configures the current node and any children nodes as a Content Receiver.

Content in this context refers to a TransferableContent that could be received from another app through Drag-and-Drop, Copy/Paste, or from the Software Keyboard.

There is no pre-filtering for the received content by media type, e.g. software Keyboard would assume that the app can handle any content that's sent to it. Therefore, it's crucial to check the received content's type and other related information before reading and processing it. Please refer to TransferableContent.hasMediaType and TransferableContent.clipMetadata to learn more about how to do proper checks on the received item.

import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.content.MediaType
import androidx.compose.foundation.content.ReceiveContentListener
import androidx.compose.foundation.content.TransferableContent
import androidx.compose.foundation.content.consume
import androidx.compose.foundation.content.contentReceiver
import androidx.compose.foundation.content.hasMediaType
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap

val state = rememberTextFieldState()
var images by remember { mutableStateOf<List<ImageBitmap>>(emptyList()) }
var dragging by remember { mutableStateOf(false) }
var hovering by remember { mutableStateOf(false) }
Column {
    Row { images.forEach { Image(bitmap = it, contentDescription = null) } }
    BasicTextField(
        state = state,
        modifier =
            Modifier.background(
                    when {
                        dragging -> Color.Red
                        hovering -> Color.Green
                        else -> MaterialTheme.colors.background
                    }
                )
                .contentReceiver(
                    receiveContentListener =
                        object : ReceiveContentListener {
                            override fun onDragStart() {
                                dragging = true
                            }

                            override fun onDragEnd() {
                                hovering = false
                                dragging = false
                            }

                            override fun onDragEnter() {
                                hovering = true
                            }

                            override fun onDragExit() {
                                hovering = false
                            }

                            override fun onReceive(
                                transferableContent: TransferableContent
                            ): TransferableContent? {
                                if (!transferableContent.hasMediaType(MediaType.Image)) {
                                    return transferableContent
                                }
                                val newImages = mutableListOf<ImageBitmap>()
                                return transferableContent
                                    .consume { item ->
                                        // only consume this item if we can read an imageBitmap
                                        item.readImageBitmap()?.let {
                                            newImages += it
                                            true
                                        } ?: false
                                    }
                                    .also { images = newImages }
                            }
                        }
                )
    )
}
Parameters
receiveContentListener: ReceiveContentListener

Listener to respond to the receive event. This interface also includes a set of callbacks for certain Drag-and-Drop state changes. Please checkout ReceiveContentListener docs for an explanation of each callback.

hasMediaType

@ExperimentalFoundationApi
fun TransferableContent.hasMediaType(mediaType: MediaType): Boolean

Returns whether this TransferableContent can provide an item with the mediaType.