How to know when a Composable like TextField gains focus? - android

I want to trigger a function upon my TextField's focus-gain, but I am unable to find something like a listener.

You can use the onFocusChanged modifier
TextField(
value = text,
onValueChange = { text = it},
modifier = Modifier.onFocusChanged {
if (it.isFocused){
//...
}
}
)

Related

Jetpack compose number input field, prevent paste text

I have input field defined like this:
BasicTextField(
keyboardOptions = KeyboardOptions(keyboardType=KeyboardType.Number),
value = text,
enabled = enabled,
singleLine = true,
textStyle = Theme.typography.Body16,
onValueChange = { onTextChange(it) },
modifier = Modifier
.fillMaxWidth(0.85f)
.onFocusChanged {
hasFocus = it.hasFocus
}
)
which allows to enter just numbers and display numeric keyboard. But users can paste any text. How to prevent pasting text ? or completely disable paste option ?
You can check if the new value is digits only
onValueChange = {
if (TextUtils.isDigitsOnly(it))
onTextChange(it)
}

Compose intercept child focus

Say I have a Row and I want it to intercept click events, preventing BasicTextField from gaining focus. Is it possible?
Row(
modifier = Modifier.clickable {}
) {
BasicTextField(...)
}
Using Enabled value in Textfield you can prevent BasicTextField from gaining focus.
TextField(
value = text,
onValueChange = { text = it},
enabled = false,
modifier = Modifier
.clickable { text= "Clicked"},
colors = TextFieldDefaults.textFieldColors(
disabledTextColor = LocalContentColor.current.copy(LocalContentAlpha.current),
disabledLabelColor = MaterialTheme.colors.onSurface.copy(ContentAlpha.medium)
)
)

Auto scrolling muli-line textfield in compose

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)
}

Android Compose show and hide keyboard

I have a composable function with TextField:
val focusManager = LocalFocusManager.current
TextField(
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Search,
),
keyboardActions = KeyboardActions(
onSearch = {
focusManager.clearFocus()
}
)
)
and I need to show keyboard from inside of composable function as well as outside of it when I click on other button which is not part of composable content. Basically I wanna call hideKeyboard() from my fragment.
I tried to use livedata inside composable:
val shouldShowKeyBoard by shouldShowSearchKeyBoard.observeAsState()
and I can do focusManager.clearFocus() to hide keyboard but I'm not sure how to show it programmatically for specific compose TextField
What's the "compose" way to manage hide/show keyboard?
You can perform some action on state changes and you can do it using the side effects.
For example you can use the LaunchedEffect function, where as a key you can pass a state you want to listen.
LaunchedEffect(booleanValue) {
//...do something
}
You can use a ViewModel to set a boolean value and something like:
// initialize focus reference to be able to request focus programmatically
val focusRequester = remember { FocusRequester() }
LaunchedEffect(viewModel.showKeyboard) {
focusRequester.requestFocus()
}
TextField(
value = text,
onValueChange = {
text = it },
modifier = Modifier
// add focusRequester modifier
.focusRequester(focusRequester)
)
Just a note:
to hide the keyboard you can also use:
val keyboardController = LocalSoftwareKeyboardController.current
TextField(
//...
keyboardActions = KeyboardActions(
onSearch = { keyboardController?.hide() }
)
Use the method focusManager.clearFocus() to dismiss the keyboard and clear the focus.
to add on Gabriele's answer, you will need val focusRequester = remember { FocusRequester() }
or you will get an exception

Get Button Text

I have a Button composable that I need to get the text value when clicked.
Button(
onClick = {// Get the "TheText" from below },
) {
Text(
modifier = Modifier.padding(8.dp),
text = "TheText",
style = TextStyle(fontSize = 15.sp)
)
}
I am creating a type of quiz where the buttons text matches the correct answer.
I thin I may need to create a custom compposabe that takes the text as a parameter and also a callback function that will pass that text back up to my main program where I can Check for a correct answer.
I assume you want to input text instead of just displaying one.
#Composable
fun example() {
var text by remember { mutableStateOf("TheText") }
Column {
Button(
onClick = {
val useThisString = text
},
) { Text(text = text) } // Probably wanna put "Copy" here
TextField(
value = text,
onValueChange = { text = it },
label = { Text("Optinal Label") }
)
}
}
Otherwise, if you just want the label of the button:
val buttonText = "TheText"
Button(
onClick = {
// Use variable here
},
) {
Text(
modifier = Modifier.padding(8.dp),
text = buttonText,
style = TextStyle(fontSize = 15.sp)
)
}
Ok here's how to store it in a variable
var retrievedValue by mutableStateOf("") //Assuming you must use it somewhere else as state
var currentValue by rememberSaveable { mutableStateOf("The Text") }
Button(
onClick = { retrievedValue = currentValue },
) {
Text(
modifier = Modifier.padding(8.dp),
text = currentValue,
style = TextStyle(fontSize = 15.sp)
)
}
Now you can use it anywhere you want. Changing the retrievedValue would trigger recompositions in any composable that reads it.
This should solve your problem. Use the retrievedValue as the value returned by a callback. In compose, for such stuff, you do not need callbacks. MutableState objects, whenever are modified, trigger a recomposition on the composables reading them.
Anyway, here when you click the button, you will get the value of the text, whatever it may be, you will always get the current value.

Categories

Resources