handwritingDetector
Modifier in Compose Foundation
Configures an element to act as a handwriting detector which detects stylus handwriting and delegates handling of the recognised text to another element.
Stylus movement on the element will start a handwriting session, and trigger the [callback]. The [callback] implementation is expected to show and focus a text input field with a [handwritingHandler] modifier which can handle the recognized text from the handwriting session.
A common use case is a component which looks like a text input field but does not actually
support text input itself, and clicking on this fake text input field causes a real text input
field to be shown. To support handwriting initiation in this case, this modifier can be applied
to the fake text input field to configure it as a detector, and a [handwritingHandler] modifier
can be applied to the real text input field. The [callback] implementation is typically the same
as the onClick
implementation for the fake text field's [clickable] modifier, which shows and
focuses the real text input field.
This function returns a no-op modifier on API levels below Android U (34) as stylus handwriting is not supported.
Last updated:
Installation
dependencies {
implementation("androidx.compose.foundation:foundation:1.8.0-alpha04")
}
Overloads
fun Modifier.handwritingDetector(callback: () -> Unit)
Parameters
name | description |
---|---|
callback | a callback which will be triggered when stylus handwriting is detected |
Code Example
HandwritingDetectorSample
@Composable
fun HandwritingDetectorSample() {
var openDialog by remember { mutableStateOf(false) }
val focusRequester = remember { FocusRequester() }
Column(
Modifier.imePadding().requiredWidth(300.dp).verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
"This is not an actual text field, but it is a handwriting detector so you can use " +
"a stylus to write here."
)
Spacer(Modifier.size(16.dp))
Text(
"Fake text field",
Modifier.fillMaxWidth()
.handwritingDetector { openDialog = !openDialog }
.padding(4.dp)
.border(
1.dp,
MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled),
RoundedCornerShape(4.dp)
)
.padding(16.dp),
color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.medium)
)
}
if (openDialog) {
Dialog(onDismissRequest = { openDialog = false }) {
Card(modifier = Modifier.width(300.dp), shape = RoundedCornerShape(16.dp)) {
Column(
modifier = Modifier.padding(24.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("This text field is a handwriting handler.")
Spacer(Modifier.size(16.dp))
val state = remember { TextFieldState() }
BasicTextField(
state = state,
modifier =
Modifier.fillMaxWidth()
.focusRequester(focusRequester)
.handwritingHandler(),
decorator = { innerTextField ->
Box(
Modifier.padding(4.dp)
.border(
1.dp,
MaterialTheme.colors.onSurface,
RoundedCornerShape(4.dp)
)
.padding(16.dp)
) {
innerTextField()
}
}
)
}
}
val windowInfo = LocalWindowInfo.current
LaunchedEffect(windowInfo) {
snapshotFlow { windowInfo.isWindowFocused }
.collect { isWindowFocused ->
if (isWindowFocused) {
focusRequester.requestFocus()
}
}
}
}
}
}