androidx.activity.compose

Classes

ManagedActivityResultLauncher

A launcher for a previously-prepared call to start the process of executing an ActivityResultContract.

Objects

Top-level functions summary

Unit
@Composable
BackHandler(enabled: Boolean, onBack: () -> Unit)

An effect for handling presses of the system back button.

Unit
@Composable
PredictiveBackHandler(
    enabled: Boolean,
    onBack: suspend (progress: Flow<BackEventCompat>) -> Unit
)

An effect for handling predictive system back gestures.

Unit

Calls Activity.reportFullyDrawn after this composition is completed.

Unit
@Composable
ReportDrawnAfter(block: suspend () -> Unit)

Adds block to the methods that must complete prior to Activity.reportFullyDrawn being called.

Unit

Adds predicate to the conditions that must be met prior to Activity.reportFullyDrawn being called.

ManagedActivityResultLauncher<I, O>
@Composable
<I : Any?, O : Any?> rememberLauncherForActivityResult(
    contract: ActivityResultContract<I, O>,
    onResult: (O) -> Unit
)

Register a request to start an activity for result, designated by the given ActivityResultContract.

Extension functions summary

Unit
ComponentActivity.setContent(
    parent: CompositionContext?,
    content: @Composable () -> Unit
)

Composes the given composable into the given activity.

Top-level properties summary

ProvidableCompositionLocal<Activity?>

Provides the android.app.Activity belonging to the current LocalContext.

Top-level functions

BackHandler

@Composable
fun BackHandler(enabled: Boolean = true, onBack: () -> Unit): Unit

An effect for handling presses of the system back button.

This effect registers a callback to be invoked when the system back button is pressed.

The onBack will be invoked when the system back button is pressed (i.e., onCompleted).

Precedence

If multiple BackHandler are present in the composition, the one that is composed last among all enabled handlers will be invoked.

Usage

It is important to call this composable unconditionally. Use the enabled parameter to control whether the handler is active. This is preferable to conditionally calling BackHandler (e.g., inside an if block), as conditional calls can change the order of composition, leading to unpredictable behavior where different handlers are invoked after recomposition.

import androidx.activity.compose.BackHandler
import androidx.compose.material.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var text by remember { mutableStateOf("") }

TextField(value = text, onValueChange = { text = it })

BackHandler(text.isNotEmpty()) {
    // handle back event
}
Parameters
enabled: Boolean = true

If true, this handler will be enabled and eligible to handle the back press.

onBack: () -> Unit

The action to be invoked when the system back button is pressed.

PredictiveBackHandler

@Composable
fun PredictiveBackHandler(
    enabled: Boolean = true,
    onBack: suspend (progress: Flow<BackEventCompat>) -> Unit
): Unit

An effect for handling predictive system back gestures.

This effect registers a callback to receive updates on the progress of system back gestures as a Flow of BackEventCompat.

The onBack lambda should be structured to handle the start, progress, completion, and cancellation of the gesture:

PredictiveBackHandler { progress: Flow<BackEventCompat> ->
// This block is executed when the back gesture begins.
try {
progress.collect { backEvent ->
// Handle gesture progress updates here.
}
// This block is executed if the gesture completes successfully.
} catch (e: CancellationException) {
// This block is executed if the gesture is cancelled.
throw e
} finally {
// This block is executed either the gesture is completed or cancelled.
}
}

Precedence

If multiple PredictiveBackHandler are present in the composition, the one that is composed last among all enabled handlers will be invoked.

Usage

It is important to call this composable unconditionally. Use the enabled parameter to control whether the handler is active. This is preferable to conditionally calling PredictiveBackHandler (e.g., inside an if block), as conditional calls can change the order of composition, leading to unpredictable behavior where different handlers are invoked after recomposition.

Timing Consideration

There are cases where a predictive back gesture may be dispatched within a rendering frame before the enabled flag is updated, which can cause unexpected behavior (see b/375343407, b/384186542). For example, if enabled is set to false, a gesture initiated in the same frame may still trigger this handler because the system sees the stale true value.

import androidx.activity.BackEventCompat
import androidx.activity.compose.BackHandler
import androidx.activity.compose.PredictiveBackHandler
import androidx.compose.material.TextField
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

var text by remember { mutableStateOf("") }

TextField(value = text, onValueChange = { text = it })

PredictiveBackHandler(text.isNotEmpty()) { progress: Flow<BackEventCompat> ->
    callback.preparePop()
    try {
        progress.collect { backEvent -> callback.updateProgress(backEvent.progress) }
        callback.popBackStack()
    } catch (e: CancellationException) {
        callback.cancelPop()
    }
}
Parameters
enabled: Boolean = true

Controls whether this handler is active. Important: Due to the timing issue described above, a gesture starting immediately after enabled is set to false may still trigger this handler.

onBack: suspend (progress: Flow<BackEventCompat>) -> Unit

The suspending lambda to be invoked by the back gesture. It receives a Flow that can be collected to track the gesture's progress.

ReportDrawn

@Composable
fun ReportDrawn(): Unit

Calls Activity.reportFullyDrawn after this composition is completed.

The Activity used is extracted from the LocalView's context.

import androidx.activity.compose.ReportDrawn
import androidx.compose.material.Text

ReportDrawn()
Text("Hello World")

ReportDrawnAfter

@Composable
fun ReportDrawnAfter(block: suspend () -> Unit): Unit

Adds block to the methods that must complete prior to Activity.reportFullyDrawn being called.

The Activity used is extracted from the LocalView's context.

After Activity.reportFullyDrawn has been called, block will not be called again, even on recomposition.

import androidx.activity.compose.ReportDrawn
import androidx.activity.compose.ReportDrawnAfter
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.remember

val lazyListState = remember { LazyListState() }
ReportDrawnAfter { lazyListState.animateScrollToItem(10) }

ReportDrawnWhen

@Composable
fun ReportDrawnWhen(predicate: () -> Boolean): Unit

Adds predicate to the conditions that must be met prior to Activity.reportFullyDrawn being called.

The Activity used is extracted from the LocalView's context.

import androidx.activity.compose.ReportDrawn
import androidx.activity.compose.ReportDrawnWhen
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

var contentComposed by remember { mutableStateOf(false) }
LazyColumn(modifier = Modifier.fillMaxSize()) {
    items(100) {
        contentComposed = true
        Text("Hello World $it")
    }
}
ReportDrawnWhen { contentComposed }

rememberLauncherForActivityResult

@Composable
fun <I : Any?, O : Any?> rememberLauncherForActivityResult(
    contract: ActivityResultContract<I, O>,
    onResult: (O) -> Unit
): ManagedActivityResultLauncher<I, O>

Register a request to start an activity for result, designated by the given ActivityResultContract.

This creates a record in the registry associated with this caller, managing request code, as well as conversions to/from Intent under the hood.

This must be called unconditionally, as part of initialization path.

You should not call ActivityResultLauncher.unregister on the returned ActivityResultLauncher. Attempting to do so will result in an IllegalStateException.

import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.result.launch
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.asImageBitmap

val result = remember { mutableStateOf<Bitmap?>(null) }
val launcher =
    rememberLauncherForActivityResult(ActivityResultContracts.TakePicturePreview()) {
        result.value = it
    }

Button(onClick = { launcher.launch() }) { Text(text = "Take a picture") }

result.value?.let { image ->
    Image(image.asImageBitmap(), null, modifier = Modifier.fillMaxWidth())
}
Parameters
contract: ActivityResultContract<I, O>

the contract, specifying conversions to/from Intents

onResult: (O) -> Unit

the callback to be called on the main thread when activity result is available

Returns
ManagedActivityResultLauncher<I, O>

the launcher that can be used to start the activity.

Extension functions

setContent

fun ComponentActivity.setContent(
    parent: CompositionContext? = null,
    content: @Composable () -> Unit
): Unit

Composes the given composable into the given activity. The content will become the root view of the given activity.

This is roughly equivalent to calling ComponentActivity.setContentView with a ComposeView i.e.:

setContentView(
ComposeView(this).apply {
setContent {
MyComposableContent()
}
}
)
Parameters
parent: CompositionContext? = null

The parent composition reference to coordinate scheduling of composition updates

content: @Composable () -> Unit

A @Composable function declaring the UI contents

Top-level properties

LocalActivity

val LocalActivityProvidableCompositionLocal<Activity?>

Provides the android.app.Activity belonging to the current LocalContext.

Note, when possible you should always prefer using the finer grained composition locals where available. This API should be used as a fallback when the required API is only available via android.app.Activity.

See androidx.compose.ui.platform.LocalConfiguration androidx.compose.ui.platform.LocalView