---
title: "InputTransformation"
description: "A function that is ran after every change made to a [TextFieldState] by user input and can change
or reject that input.

Input transformations are ran after hardware and software keyboard events, when text is pasted or
dropped into the field, or when an accessibility service changes the text.

To chain filters together, call [then].

Prebuilt filters are provided for common filter operations. See:
- [InputTransformation].[maxLength]`()`
- [InputTransformation].[allCaps]`()`"
type: "interface"
---

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


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

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



```kotlin
fun interface InputTransformation
```


A function that is ran after every change made to a `TextFieldState` by user input and can change
or reject that input.

Input transformations are ran after hardware and software keyboard events, when text is pasted or
dropped into the field, or when an accessibility service changes the text.

To chain filters together, call `then`.

Prebuilt filters are provided for common filter operations. See:
- `InputTransformation`.`maxLength``()`
- `InputTransformation`.`allCaps``()`


## Properties

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


```kotlin
val keyboardOptions: KeyboardOptions?
```


Optional `KeyboardOptions` that will be used as the default keyboard options for configuring
the IME. The options passed directly to the text field composable will always override this.



## Functions

```kotlin
fun SemanticsPropertyReceiver.applySemantics() = Unit
```


Optional semantics configuration that can update certain characteristics of the applied
TextField, e.g. `SemanticsPropertyReceiver.maxTextLength`.


```kotlin
fun TextFieldBuffer.transformInput()
```


The transform operation. For more information see the documentation on `InputTransformation`.

This function is scoped to `TextFieldBuffer`, a buffer that can be changed in-place to alter
or reject the changes or set the selection.

To reject all changes in the scoped `TextFieldBuffer`, call
`revertAllChanges`.

When multiple `InputTransformation`s are linked together, the `transformInput` function of
the first transformation is invoked before the second one. Once the changes are made to
`TextFieldBuffer` by the initial `InputTransformation` in the chain, the same instance of
`TextFieldBuffer` is forwarded to the subsequent transformation in the chain. Note that
`TextFieldBuffer.originalValue` never changes while the buffer is passed along the chain.
This sequence persists until the chain reaches its conclusion.



## Code Examples

### BasicTextFieldCustomInputTransformationSample
```kotlin
@Composable
fun BasicTextFieldCustomInputTransformationSample() {
    // Demonstrates how to create a custom and relatively complex InputTransformation.
    val state = remember { TextFieldState() }
    BasicTextField(
        state,
        inputTransformation =
            InputTransformation {
                // A filter that always places newly-input text at the start of the string, after a
                // prompt character, like a shell.
                val promptChar = '>'
                fun CharSequence.countPrefix(char: Char): Int {
                    var i = 0
                    while (i < length && get(i) == char) i++
                    return i
                }
                // Step one: Figure out the insertion point.
                val newPromptChars = asCharSequence().countPrefix(promptChar)
                val insertionPoint = if (newPromptChars == 0) 0 else 1
                // Step two: Ensure text is placed at the insertion point.
                if (changes.changeCount == 1) {
                    val insertedRange = changes.getRange(0)
                    val replacedRange = changes.getOriginalRange(0)
                    if (!replacedRange.collapsed && insertedRange.collapsed) {
                        // Text was deleted, delete forwards from insertion point.
                        delete(insertionPoint, insertionPoint + replacedRange.length)
                    }
                }
                // Else text was replaced or there were multiple changes - don't handle.
                // Step three: Ensure the prompt character is there.
                if (newPromptChars == 0) {
                    insert(0, ">")
                }
                // Step four: Ensure the cursor is ready for the next input.
                placeCursorAfterCharAt(0)
            },
    )
}
```

