:arrows_clockwise: material3.OutlinedTextField cur...
# compose
t
🔃 material3.OutlinedTextField cursor position issue I enter text in the input field and then rotate the device. Then the text cursor is positioned before the first character. Does anyone know how to resolve this?
Copy code
Code example in the thread ...
l
Did you add the manifest line that allows compose to handle orientation changes? If not, then the activity is probably getting re-created on orientation change.
t
Not intentionally. What is the recommended value for
android:configChanges
when using Compose resp. both XML and Compose across the app?
Copy code
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.OutlinedTextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import com.example.outlinedtextfieldtest.ui.theme.OutlinedTextFieldTestTheme

class MainActivity : ComponentActivity() {

    private var content: Content = Content()

    @ExperimentalMaterial3Api
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Screen(content.text) {
                content = content.copy(text = it)
            }
        }
    }
}


@ExperimentalMaterial3Api
@Composable
private fun Screen(text: String, onTextChanged: (String) -> Unit) {
    OutlinedTextFieldTestTheme {
        val focusRequester = remember { FocusRequester() }
        var localText by rememberSaveable { mutableStateOf(text) }
        OutlinedTextField(
            modifier = Modifier.focusRequester(focusRequester),
            value = localText,
            onValueChange = {
                localText = it
                onTextChanged(it)
            },
        )
        LaunchedEffect(focusRequester) {
            focusRequester.requestFocus()
        }

    }
}

private data class Content(val text: String = "")
p
Adam said autocomplete them all 🤷🏻
l
How much of the app is Compose vs XML, and importantly, what’s XML? If the XML needs to respond to config changes, it’s a lot more difficult, but if the navigation and orientation are handled in Compose, and XML is just sub-views, you can just use the compose method.
s
Also of you use compose dialogs you can't do it either since rotating your device won't trigger them to re-adjust to the new space available to them.
t
Do you know of official guidance in the Google docs? I could not find it explicitly being explained.
s
There isn't anything in the official docs regarding this https://kotlinlang.slack.com/archives/CJLTWPH7S/p1680021891960939?thread_ts=1680020476.757029&cid=CJLTWPH7S since it still has some gotchas so they can't suggest this to everyone without also explaining all the things you need to be careful about.
t
I see. I have a look at my project to see if I can apply is to my activity. Thank you for the pointer.
e
if you use the
TextFieldValue
overload instead of the
String
overload, you'll receive and be able to change the cursor/selection position(s)
s
And notably, TextFieldValue does have a
Saver
in its companion object, so you can do
rememberSaveable
and this will survive your rotation and activity recreation