The Developer Preview for Android 11 is now available; test it out and share your feedback.


interface VisualTransformation

Interface used for changing visual output of the input field.

This interface can be used for changing visual output of the text in the input field. For example, you can mask characters in password filed with asterisk with PasswordVisualTransformation.


Public methods

abstract TransformedText

Change the visual output of given text.

Inherited extension functions

From androidx.compose
operator T

IMPORTANT: This global operator is TEMPORARY, and should be removed whenever an answer for contextual composers is reached.

Public methods


abstract fun filter(text: AnnotatedString): TransformedText

Change the visual output of given text.

Note that the returned text length can be different length from the given text. The composable will call the offset translator for converting offsets for various reasons, cursor drawing position, text selection by gesture, etc.

Example: The ASCII only password (replacing with '*' chars) original text : thisispassword transformed text: **************

import androidx.ui.input.TransformedText
import androidx.ui.text.AnnotatedString

return TransformedText(

     * [OffsetMap.identityOffsetMap] is a predefined [OffsetMap] that can be used for the
     * transformation that does not change the character count.
Example: Credit Card Visual Output (inserting hyphens each 4 digits)original text : 1234567890123456transformed text: 1234-5678-9012-3456
import androidx.ui.input.TransformedText
import androidx.ui.text.AnnotatedString

// Making XXXX-XXXX-XXXX-XXXX string.
val trimmed = if (text.text.length >= 16) text.text.substring(0..15) else text.text
var out = ""
for (i in trimmed.indices) {
    out += trimmed[i]
    if (i % 4 == 3 && i != 15) out += "-"

 * The offset translator should ignore the hyphen characters, so conversion from
 *  original offset to transformed text works like
 *  - The 4th char of the original text is 5th char in the transformed text.
 *  - The 13th char of the original text is 15th char in the transformed text.
 *  Similarly, the reverse conversion works like
 *  - The 5th char of the transformed text is 4th char in the original text.
 *  - The 12th char of the transformed text is 10th char in the original text.
val creditCardOffsetTranslator = object : OffsetMap {
    override fun originalToTransformed(offset: Int): Int {
        if (offset <= 3) return offset
        if (offset <= 7) return offset + 1
        if (offset <= 11) return offset + 2
        if (offset <= 16) return offset + 3
        return 19

    override fun transformedToOriginal(offset: Int): Int {
        if (offset <= 4) return offset
        if (offset <= 9) return offset - 1
        if (offset <= 14) return offset - 2
        if (offset <= 19) return offset - 3
        return 16

return TransformedText(AnnotatedString(out), creditCardOffsetTranslator)
text: AnnotatedString The original text
the pair of filtered text and offset translator.