I have a Box with textfield inside. i want to hide keyboard by touching on the Box and use modifier of Box for it:
.onFocusEvent { focusState ->
if (focusState.isFocused) {
keyboardController?.hide()
}
}
But this applies to the text field as well, so the keyboard doesn't show up at all.
How can i fix it?
You can use the InteractionSource to know if the TextField is focused.
Something like:
var text by remember { mutableStateOf("")}
val interactionSource = remember { MutableInteractionSource() }
val isFocused = interactionSource.collectIsFocusedAsState().value
val keyboardController = LocalSoftwareKeyboardController.current
Box(Modifier
.fillMaxWidth()
.clickable {
if (isFocused) keyboardController?.hide()
}
){
TextField(
text,
onValueChange = { text = it },
interactionSource = interactionSource
)
}
Related
I have a lazy column that contains a number of Text(string = "...") and a textfield pinned to the bottom of the screen below the LazyColumn. when the textfield is focused, the keyboard shows up and it pushes the textfield above the keyboard which is expected. however, when the items in the LazyColumn r too much, the textfield goes below the keyboard instead of allowing the user to scroll the lazy column. any reason for this? I already have set
android:windowSoftInputMode="adjustResize" in my manifest's activity. here's the full code:
Column(modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.SpaceBetween) {
LazyColumn {
items(viewModel.options) { option ->
Text(option.message)
}
}
Row(modifier = Modifier.fillMaxWidth()) {
TextField(
modifier = Modifier.weight(1f),
value = optionsText,
onValueChange = {optionsText = it },
singleLine = true
)
Icon(
Icons.Filled.Send,
contentDescription = "",
modifier = Modifier.align(Alignment.CenterVertically).clickable {...}
)
}
}
Solution, WEIGHTS 🤪 !
LazyColumn(Modifier.weight(9f)) {
items(listItems) {
Text(it)
}
}
Row(modifier = Modifier.fillMaxWidth().weight(1f, /*false*/)) {
var loremText by remember { mutableStateOf("") }
TextField(
modifier = Modifier.weight(1f),
value = loremText,
onValueChange = { loremText = it },
singleLine = true
)
Icon(
Icons.Filled.Send,
contentDescription = "",
modifier = Modifier
.align(Alignment.CenterVertically)
.clickable { }
)
}
You may remove the adjustResize from your manifest.
I'm using the below code to try and request focus to a textfield and have the keyboard come up. Currently the textfield does request focus but the keyboard fails to show. This same code works in another project im working on, but the difference here is this code is inside a Dialog composable, and the other code isn't, so I'm not sure if its the Dialog making the keyboard fail to show?
val textField = remember { FocusRequester() }
Dialog(onDismissRequest = {
openDialog.value = false
dialogInput.value = ""
}) {
Column(
modifier = Modifier
.height(274.dp)
.background(Color.Transparent)
.clickable {
openDialog.value = false
dialogInput.value = ""
}
) {
OutlinedTextField(
modifier = Modifier
.height(64.dp)
.background(Color.White)
.focusRequester(textField),
label = {
Text(
text = label,
style = MaterialTheme.typography.body2.copy(color = Color.Black)
)
},
value = dialogInput.value,
onValueChange = {
dialogInput.value = it
events.filterPlayers(it)
},
textStyle = MaterialTheme.typography.body2.copy(color = Color.Black),
colors = TextFieldDefaults.textFieldColors(
backgroundColor = Color.White,
unfocusedIndicatorColor = Color.White,
focusedIndicatorColor = Color.White
)
)
DisposableEffect(Unit) {
textField.requestFocus()
onDispose {}
}
}
val focusRequester = FocusRequester()
LocalView.current.viewTreeObserver.addOnWindowFocusChangeListener {
if (it) focusRequester.requestFocus()
}
this work for me, after window for dialog get focused, request focus for TextField would show soft keyboard automatically.
When initially clicking the text field the whole view correctly shifts upwards so the keyboard is just below text entry.
After pressing return on the keyboard nothing on the screen moves and it leaves the cursor under the keyboard out of vision.
I had some other TextField issues that were solve by using the accompanist library. There is currently an assigned issue for it here. Here is the composable for the textField:
#Composable
fun EditTextContent(
label: String,
text: String,
isError: Boolean,
modifier: Modifier = Modifier,
singleLine: Boolean,
inputType: KeyboardType = KeyboardType.Text,
onTextChanged: (String) -> Unit
) {
val focusManager = LocalFocusManager.current
OutlinedTextField(
modifier = modifier.navigationBarsWithImePadding().testTag(label),
value = text,
onValueChange = {
onTextChanged(it)
},
label = { Text(label) },
singleLine = singleLine,
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
keyboardOptions = KeyboardOptions(keyboardType = inputType),
isError = isError,
trailingIcon = {
if (isError) {
Icon(
painter = painterResource(id = R.drawable.ic_warning),
modifier = Modifier.size(25.dp),
contentDescription = null
)
} else {
null
}
},
)
}
Activity in the manifest is set to android:windowSoftInputMode="adjustPan" since adjustResize does nothing for some reason. Any help would be appreciated.
I have a screen with several focusable widgets for TV.
Every time I have to click the direction key then Box01 get focused.
Does anyone know how to set Box01 focused by default?
My Code:
#Composable
fun DefaultFocusSample(){
Row(Modifier.padding(100.dp)) {
FocusBox("Box01")
Spacer(modifier = Modifier.padding(10.dp))
FocusBox("Box02")
Spacer(modifier = Modifier.padding(10.dp))
FocusBox("Box03")
Spacer(modifier = Modifier.padding(10.dp))
FocusBox("Box04")
}
}
#Composable
fun FocusBox(text:String){
var color by remember { mutableStateOf(White) }
Box(
Modifier
.onFocusChanged {
color = if (it.isFocused) Green else White }
.focusable()
.border(2.dp,color)
){
Text(text = text,
modifier = Modifier.padding(10.dp))
}
}
To manually bring focus to focusable, you can use FocusRequester, like this:
#Composable
fun FocusBox(text:String, requester: FocusRequester = FocusRequester()){
var color by remember { mutableStateOf(Color.White) }
Box(
Modifier
.focusRequester(requester)
.onFocusChanged {
color = if (it.isFocused) Color.Green else Color.White
}
.focusable()
.border(2.dp, color)
) {
Text(text = text,
modifier = Modifier.padding(10.dp))
}
}
Row(
Modifier
.background(Color.Yellow)
.padding(10.dp)
) {
val requester = FocusRequester()
FocusBox("Box01", requester)
LaunchedEffect(Unit) {
requester.requestFocus()
}
Spacer(modifier = Modifier.padding(10.dp))
FocusBox("Box02")
Spacer(modifier = Modifier.padding(10.dp))
FocusBox("Box03")
Spacer(modifier = Modifier.padding(10.dp))
FocusBox("Box04")
}
LaunchedEffect is a side effect, it'll be run only once when composable appears. Check out more in the documentation
I want the keyboard to pop up by an auto requesting focus on a text field in jetpack compose when the user navigates to a composable. As of now, this is what I have tried but it doesn't seem to work
val feedbackContent = remember { mutableStateOf(TextFieldValue()) }
val focusRequester = remember { FocusRequester() }
OutlinedTextField(
modifier = Modifier
.clickable {
focusRequester.requestFocus()
}
.fillMaxWidth()
.focusRequester(focusRequester)
.focusable()
)
You can use something like:
val focusRequester = FocusRequester()
val keyboardController = LocalSoftwareKeyboardController.current
OutlinedTextField(
value = text,
onValueChange = { text = it},
modifier = Modifier
.fillMaxWidth()
.focusRequester(focusRequester)
.onFocusChanged {
if (it.isFocused) {
keyboardController?.show()
}
}
)
DisposableEffect(Unit) {
focusRequester.requestFocus()
onDispose { }
}