Compose Unstyled 2.0 is out! Check the official announcement blog ->
Class

TextFieldBuffer

A text buffer that can be edited, similar to StringBuilder.

Source set: Common
class TextFieldBuffer
internal constructor(
    initialValue: TextFieldCharSequence,
    initialChanges: ChangeTracker? = null,
    internal val originalValue: TextFieldCharSequence = initialValue,
    private val offsetMappingCalculator: OffsetMappingCalculator? = null,
) : Appendable

A text buffer that can be edited, similar to StringBuilder.

This class provides methods for changing the text, such as:

This class also stores and tracks the cursor position or selection range. The cursor position is just a selection range with zero length. The cursor and selection can be changed using methods such as:

To get one of these, and for usage samples, see TextFieldState.edit. Every change to the buffer is tracked in a ChangeList which you can access via the changes property.

Properties

length

Source set: Common
val length: Int

The number of characters in the text field.

originalText

Source set: Common
val originalText: CharSequence

Original text content of the buffer before any changes were applied. Calling revertAllChanges will set the contents of this buffer to this value.

originalSelection

Source set: Common
val originalSelection: TextRange

Original selection before the changes. Calling revertAllChanges will set the selection to this value.

changes

Source set: Common
@ExperimentalFoundationApi
val changes: ChangeList

The ChangeList represents the changes made to this value and is inherently mutable. This means that the returned ChangeList always reflects the complete list of changes made to this value at any given time, even those made after reading this property.

hasSelection

Source set: Common
val hasSelection: Boolean

True if the selection range has non-zero length. If this is false, then the selection represents the cursor.

selection

Source set: Common
var selection: TextRange

The selected range of characters.

Places the selection around the given range in characters.

If the start or end of TextRange fall inside surrogate pairs or other invalid runs, the values will be adjusted to the nearest earlier and later characters, respectively.

To place the start of the selection at the beginning of the field, set this value to TextRange.Zero. To place the end of the selection at the end of the field, after the last character, pass TextFieldBuffer.length. Passing a zero-length range is the same as calling placeCursorBeforeCharAt.

textRange

Source set: Common
var TrackedRange<*>.textRange: TextRange

The TextRange of this style. This range will reflect the up-to-date style range as the text is edited.

This property is only accessible within the TextFieldBuffer block where the TrackedRange was created. Do not keep a reference to the TrackedRange outside of that block.

Modifying the text can potentially invalidate a TrackedRange if its length collapses to zero. It is recommended to check valid before accessing this property if any text changes were made, or if the range might have been explicitly removed via removeStyle.

Setting this property will update the range of the style in-place, preserving its original applying order relative to other styles in the buffer.

spanStyle

Source set: Common
var TrackedRange<SpanStyle>.spanStyle: SpanStyle

The SpanStyle object associated with this TrackedRange.

This property is only accessible within the TextFieldBuffer block where the TrackedRange was created.

Modifying the text can potentially invalidate a TrackedRange if its length collapses to zero. It is recommended to check valid before accessing this property if any text changes were made, or if the range might have been explicitly removed via removeStyle.

Setting this property will update the style applied to the text in-place, preserving its original applying order relative to other styles in the buffer.

paragraphStyle

Source set: Common
var TrackedRange<ParagraphStyle>.paragraphStyle: ParagraphStyle

The ParagraphStyle object associated with this TrackedRange.

This property is only accessible within the TextFieldBuffer block where the TrackedRange was created.

Modifying the text can potentially invalidate a TrackedRange if its length collapses to zero. It is recommended to check valid before accessing this property if any text changes were made, or if the range might have been explicitly removed via removeStyle.

Setting this property will update the style applied to the text in-place, preserving its original applying order relative to other styles in the buffer.

valid

Source set: Common
val TrackedRange<*>.valid: Boolean

Whether this TrackedRange is still valid in the buffer.

A style ceases to exist when removeStyle is called or when its range collapses to a length of zero due to text edits. Once it no longer exists, accessing or modifying its properties will throw an IllegalStateException.

This property is only accessible within the TextFieldBuffer scope where the TrackedRange was created.

expandPolicy

Source set: Common
var TrackedRange<*>.expandPolicy: ExpandPolicy

The ExpandPolicy defining how the style range expands when text is inserted at its boundaries.

This property is only accessible within the TextFieldBuffer scope where the TrackedRange was created.

Modifying the text can potentially invalidate a TrackedRange if its length collapses to zero. It is recommended to check valid before accessing this property if any text changes were made, or if the range might have been explicitly removed via removeStyle.

Setting this property will update the expand policy in-place, preserving its original applying order relative to other styles in the buffer.

Functions

replace

fun replace(start: Int, end: Int, text: CharSequence)

Replaces the text between start (inclusive) and end (exclusive) in this value with text, and records the change in changes.

Parameters

start The character offset of the first character to replace.
end The character offset of the first character after the text to replace.
text The text to replace the range [start, end) with.

charAt

fun charAt(index: Int): Char

Returns the Char at index in this buffer.

asCharSequence

fun asCharSequence(): CharSequence

Returns a CharSequence backed by this buffer. Any subsequent changes to this buffer will be visible in the returned sequence as well.

revertAllChanges

fun revertAllChanges()

Revert all changes made to this value since it was created.

After calling this method, this object will be in the same state it was when it was initially created, and changes will be empty.

placeCursorBeforeCharAt

fun placeCursorBeforeCharAt(index: Int)

Places the cursor before the character at the given index.

If index is inside a surrogate pair or other invalid run, the cursor will be placed at the nearest earlier index.

To place the cursor at the beginning of the field, pass index 0. To place the cursor at the end of the field, after the last character, pass index TextFieldBuffer.length or call placeCursorAtEnd.

Parameters

index Character index to place cursor before, should be in range 0 to TextFieldBuffer.length, inclusive.

placeCursorAfterCharAt

fun placeCursorAfterCharAt(index: Int)

Places the cursor after the character at the given index.

If index is inside a surrogate pair or other invalid run, the cursor will be placed at the nearest later index.

To place the cursor at the end of the field, after the last character, pass index TextFieldBuffer.length or call placeCursorAtEnd.

Parameters

index Character index to place cursor after, should be in range 0 (inclusive) to TextFieldBuffer.length (exclusive).

addStyle

fun addStyle(spanStyle: SpanStyle, start: Int, end: Int)

Adds the given spanStyle to the text between start and end on this buffer.

Styles are applied in the order they are added to the buffer. This order is preserved even as the text is edited and style ranges are adjusted.

Note that the same SpanStyle object can be added to multiple distinct ranges. Each call to addStyle creates a new, independent style range. This allows you to save object allocations by applying the same style object to different distinct ranges.

If ComposeFoundationFlags.isBasicTextFieldStyledTextEnabled is enabled, this function can be called from any TextFieldBuffer scope (such as InputTransformation or TextFieldState.edit). The added style will be tracked and its range will automatically adjust as the text is edited, behaving as if called with ExpandPolicy.AtEnd.

If the flag is disabled, this function is only permitted within an OutputTransformation. Any styling added in this mode will not become part of the underlying text state, nor will its boundaries be tracked or updated during subsequent edits. For predictable results when the flag is disabled, it is recommended to apply styles only after the text content has been fully determined.

addStyle

fun addStyle(paragraphStyle: ParagraphStyle, start: Int, end: Int)

Adds the given paragraphStyle to the text between start and end on this buffer.

Styles are applied in the order they are added to the buffer. This order is preserved even as the text is edited and style ranges are adjusted.

Note that the same ParagraphStyle object can be added to multiple distinct ranges. Each call to addStyle creates a new, independent style range. This allows you to save object allocations by applying the same style object to different distinct ranges.

If ComposeFoundationFlags.isBasicTextFieldStyledTextEnabled is enabled, this function can be called from any TextFieldBuffer scope (such as InputTransformation or TextFieldState.edit). The added style will be tracked and its range will automatically adjust as the text is edited, behaving as if called with ExpandPolicy.AtEnd.

If the flag is disabled, this function is only permitted within an OutputTransformation. Any styling added in this mode will not become part of the underlying text state, nor will its boundaries be tracked or updated during subsequent edits. For predictable results when the flag is disabled, it is recommended to apply styles only after the text content has been fully determined.

addStyle

fun addStyle(
        spanStyle: SpanStyle,
        range: TextRange,
        expandPolicy: ExpandPolicy,
    ): TrackedRange<SpanStyle>

Adds the given spanStyle to the text within the range on this buffer.

Styles are applied in the order they are added to the buffer. This order is preserved even as the text is edited and style ranges are adjusted.

Note that the same SpanStyle object can be added to multiple distinct ranges. Each call to addStyle creates a new, independent style range, and returns a unique TrackedRange to identify it. This allows you to save object allocations by applying the same style object to different distinct ranges.

Parameters

spanStyle the SpanStyle to be applied
range the effective range of the SpanStyle
expandPolicy the ExpandPolicy defining how the style range expands when text is inserted at its boundaries.

Returns

a TrackedRange referencing the added style.

addStyle

fun addStyle(
        paragraphStyle: ParagraphStyle,
        range: TextRange,
        expandPolicy: ExpandPolicy,
    ): TrackedRange<ParagraphStyle>

Adds the given paragraphStyle to the text within the range on this buffer.

Styles are applied in the order they are added to the buffer. This order is preserved even as the text is edited and style ranges are adjusted.

Note that the same ParagraphStyle object can be added to multiple distinct ranges. Each call to addStyle creates a new, independent style range, and returns a unique TrackedRange to identify it. This allows you to save object allocations by applying the same style object to different distinct ranges.

Parameters

paragraphStyle the ParagraphStyle to be applied
range the effective range of the ParagraphStyle
expandPolicy the ExpandPolicy defining how the style range expands when text is inserted at its boundaries.

Returns

a TrackedRange referencing the added style.

getSpanStyles

fun getSpanStyles(start: Int, end: Int): List<TrackedRange<SpanStyle>>

Returns the SpanStyles that intersect with the given range defined by start (inclusive) and end (exclusive).

Styles are returned in the same order they were originally added to the buffer.

A style intersects with the range if it overlaps with it at any point. For non-empty ranges, this means style.start < end and start < style.end.

Example Query Range: [5, 15)

0    5    10   15   20   25
|----|----|----|----|----|    [---------)              Query Range [5, 15)

[-------------------)         Style [0, 20) (Contains query) -> Returned         [----)              Style [8, 12) (Inside query)   -> Returned
[----------)                  Style [0, 10) (Overlap start)  -> Returned
[----)                        Style [0, 5)  (Touching start) -> NOT Returned              [----------)   Style [15, 25)(Touching end)   -> NOT Returned

Example Collapsed Query: [10, 10)

0    5    10   15   20   25
|----|----|----|----|----|         |                   Query Range [10, 10)

[-------------------)         Style [0, 20) (Contains query) -> Returned
[----------)                  Style [0, 10) (Touching end)   -> NOT Returned         [----------)        Style [10, 20)(Touching start) -> Returned

Parameters

start the inclusive start offset of the range
end the exclusive end offset of the range

Returns

a list of TrackedRanges referencing the styles intersecting with the given range, returned in the order they were added to the buffer.

getParagraphStyles

fun getParagraphStyles(start: Int, end: Int): List<TrackedRange<ParagraphStyle>>

Returns the ParagraphStyles that intersect with the range defined by start (inclusive) and end (exclusive).

Styles are returned in the same order they were originally added to the buffer.

A style intersects with the range if it overlaps with it at any point. For non-empty ranges, this means style.start < end and start < style.end.

Example Query Range: [5, 15)

0    5    10   15   20   25
|----|----|----|----|----|    [---------)              Query Range [5, 15)

[-------------------)         Style [0, 20) (Contains query) -> Returned         [----)              Style [8, 12) (Inside query)   -> Returned
[----------)                  Style [0, 10) (Overlap start)  -> Returned
[----)                        Style [0, 5)  (Touching start) -> NOT Returned              [----------)   Style [15, 25)(Touching end)   -> NOT Returned

Example Collapsed Query: [10, 10)

0    5    10   15   20   25
|----|----|----|----|----|         |                   Query Range [10, 10)

[-------------------)         Style [0, 20) (Contains query) -> Returned
[----------)                  Style [0, 10) (Touching end)   -> NOT Returned         [----------)        Style [10, 20)(Touching start) -> Returned

Parameters

start the inclusive start offset of the range
end the exclusive end offset of the range

Returns

a list of TrackedRanges referencing the styles intersecting with the given range, returned in the order they were added to the buffer.

removeStyle

fun removeStyle(trackedRange: TrackedRange<*>): Boolean

Removes the exact style represented by the given trackedRange from this buffer. This method only removes the specific style range tied to this TrackedRange object. Since trackedRange uniquely identifies a style range, it does not remove other styles that happen to occupy the same text range.

Parameters

trackedRange the TrackedRange referencing the specific style range to be removed. If the trackedRange was not added to this buffer, or has already been removed, this method will do nothing and return false.

Returns

true if the given trackedRange is found in the TextFieldBuffer and successfully removed, false otherwise.

Last updated: