On tapping a TextField, created with Jetpack compose, the label of TextField moves upward. How do we disable this?
Or is there any other way the TexField would work like an EditText in View system where we have hint which disappears on tapping the EditText?
Jetpack compose version - 1.0.3
placeholder attribute might be what you are looking for.
But, the text doesn't disappear on clicking the TextField.
It disappears only when the user enters some input text.
Default state
Focused state
After entering input
Code
TextField(
placeholder = { Text(text = "Label") },
// Other attributes
)
UPDATE
You can use placeholder with state.
var focusState by remember { mutableStateOf(false) }
placeholder = {
Text(
text = if (focusState) "" else "label",
)
}
and focusState you take from onFocusChanged
TextField(
modifier = Modifier
.onFocusChanged { focus ->
focusState = focus.isFocused
}
Related
I have a BasicTextField in my jetpack compose function. When i click(user has input some text into the textfield by now) on a button to navigate to another composable in my NavHost, and from that new view click on back to the composable which i came from which has the textfield, the textfield is empty. I want to keep the text that the user typed in before navigating, but I can't figure it out how. Have looked here but found no answer.
Suggestions?
Here is my code:
#Composable
fun SearchBar(
modifier: Modifier = Modifier,
onSearch: (String) -> Unit = {}
) {
var text by remember {
mutableStateOf("")
}
Box(modifier = modifier) {
BasicTextField(
value = text,
onValueChange = {
text = it
onSearch(it)
},
maxLines = 1,
singleLine = true,
textStyle = TextStyle(color = Color.Black),
modifier = Modifier
.fillMaxWidth()
.shadow(5.dp, CircleShape)
.background(Color.White, CircleShape)
)
}
}
remember saves the value over recomposition (i.e., when your state changes, your composable automatically recomposes with the new state).
As per the Restore UI State guide, you can replace remember with rememberSaveable to save your state across:
Configuration changes
Process death and recreation
Your composable being put on the NavHost back stack
As well as any other case where your SearchBar could be removed from composition and then re-added (such as if you were using in Accompanist's Pager or in a LazyColumn or LazyRow).
var text by rememberSaveable {
mutableStateOf("")
}
I want to show a dialog and automatically set focus to a OutlinedTextField, so user can instantly start typing.
I ended up with text field does get focus, does get the cursor flickering, but the keyboard remains hidden. So user still has to click on a textField to make the keyboard appear.
Here is how I'm doing this
LaunchedEffect(Unit) {
focusRequester.requestFocus()
}
OutlinedTextField(
value = text,
modifier = Modifier
.focusRequester(focusRequester)
.fillMaxWidth(),
onValueChange = {
text = it
}
)
To make keyboard show up, you should place a delay before requesting the focus:
LaunchedEffect(Unit) {
delay(200)// <-- This is crucial.
focusRequester.requestFocus()
}
OutlinedTextField(
value = text,
modifier = Modifier
.focusRequester(focusRequester)
.fillMaxWidth(),
onValueChange = {
text = it
}
)
The delay time may be changed. For me it starts working starting from 100ms. If it still doesn't work with 200, increase it until it works. I believe it's all about performance of the devcie, so the higher the delay, the more slow devices can be used.
I have a TextField in column with verticalScroll().
When adding a large number of characters, the textfield size goes beyond the keyboard and I stop seeing what I am typing
I tried to use this lib, but that's doesn't help
I think you can use BringIntoViewRequester in your TextField.
var state by rememberSaveable {
mutableStateOf("")
}
val coroutineScope = rememberCoroutineScope()
val bringIntoViewRequester = remember {
BringIntoViewRequester()
}
TextField(
value = state,
onValueChange = { text ->
state = text
// This will cause the TextField be repositioned on the screen
// while you're typing
coroutineScope.launch {
bringIntoViewRequester.bringIntoView()
}
},
modifier = Modifier
.bringIntoViewRequester(bringIntoViewRequester)
.onFocusChanged {
if (it.isFocused) {
coroutineScope.launch {
delay(400) // delay to way the keyboard shows up
bringIntoViewRequester.bringIntoView()
}
}
},
)
See the complete sample here.
you can add android:ellipsize="end" and android:maxLines="1" or whatever lines you want, in your text xml hope it would be helpful.
I've a multi-line text field as below
val scrollState = rememberScrollState(0)
TextField(
modifier = Modifier
.fillMaxWidth()
.height(75.dp)
.verticalScroll(scrollState),
value = caption,
onValueChange = { onCaptionChanged(it) }
)
Currently, it support manual scrolling but i want it to scroll down automatically when user enter new line (\n). How do i achieve that?
You can scroll using scrollState.scrollTo. To track content height change, you can check scrollState.maxValue, for example like this:
LaunchedEffect(scrollState.maxValue) {
scrollState.scrollTo(scrollState.maxValue)
// or
// scrollState.animateScrollTo(scrollState.maxValue)
}
Is there a way to disable all interaction for Jetpack Compose's TextField?
You can use the enabled attribute:
enabled : controls the enabled state of the TextField. When false, the text field will be neither editable nor focusable, the input of the text field will not be selectable, visually text field will appear in the disabled UI state
Something like:
var text by rememberSaveable { mutableStateOf("Text") }
TextField(
value = text,
onValueChange = { text = it },
enabled = false,
label = { Text("Label") },
singleLine = true
)
My project is on alpha08 atm. Hopefully they add some built in way of doing this soon but in the meantime I've been doing this:
val textState = remember { mutableStateOf(TextFieldValue()) }
val disabled = remember { mutableStateOf(true) }
Box {
TextField(value = textState.value, onValueChange = {
textState.value = it
})
if (disabled.value) {
// Set alpha(0f) to hide click animation
Box(modifier = Modifier.matchParentSize().alpha(0f).clickable(onClick = {}))
}
}
So yeah, drawing an invisible clickable Box that's the same size over the TextField. You can resize the TextField to whatever you'd want, calling .matchParentSize() on the invisible Box will make it match the TextField due to them being the only children in the parent Box.
You can toggle the disabled state by setting disabled.value = true/false wherever is appropriate.
readOnly attribute can also work in case if you want focusable & selectable text field but not editable.
Like this:
var value by remember { mutableStateOf("Hello World!") }
TextField(
value = value,
onValueChange = { value = it },
readOnly = true,
)