Skip to content

BasicTextField selection collapses to a zero span at the cursor location when focus is lost #2569

@kirill-grouchnikov

Description

Here is the sample to reproduce this on 1.2.0 and 1.3.0-rc01:

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.ExperimentalUnitApi
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.*

@ExperimentalUnitApi
fun main() = application {
    val state = rememberWindowState(
        placement = WindowPlacement.Floating,
        position = WindowPosition.Aligned(Alignment.Center),
        size = DpSize(600.dp, 400.dp)
    )

    Window(
        title = "Demo",
        state = state,
        onCloseRequest = ::exitApplication
    ) {
        SampleStyles()
    }
}


@ExperimentalUnitApi
@Composable
fun SampleStyles() {
    var textSelectionRange by remember { mutableStateOf(TextRange.Zero) }
    println("Range $textSelectionRange")

    Column(modifier = Modifier.fillMaxSize()) {
        Row(modifier = Modifier.fillMaxWidth()) {
            Button(onClick = {}) {
                Text("Sample")
            }
        }
        BasicTextField(
            value = TextFieldValue(
                text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor",
                selection = textSelectionRange
            ),
            onValueChange = {
                println("Changing range to ${it.selection}")
                textSelectionRange = it.selection
            },
            modifier = Modifier.fillMaxWidth().fillMaxHeight(fraction = 1.0f)
        )
    }
}

Run the app. Select a range in the text - it will print the selected range in the console. Now click the button at the top of the window and look at the updated range printed in the console.

JetBrains/compose-multiplatform-core@ca869b1#diff-42592036468eac046f04d9f25ac21f134ed22d3b55e602da3c56bb0c9f206a7c may be the change that caused this behavior change. Note that version 1.1.0 and the Android variant do not lose the selection on focus loss.

In Swing, by the way, selection is not lost on focus loss. It is not drawn by default, and there is a workaround to keep the selection visible:

            textPane.setCaret(new DefaultCaret() {
                @Override
                public void setSelectionVisible(boolean visible) {
                    super.setSelectionVisible(true);
                }
            });

The target use case is a simple text editor that allows toggling bold, italic, underline, strikethrough, font size, font family on the selected span. Think a text pane with a strip of buttons on the side to initiate those actions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdesktop

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions