my textfield is overshadoved when I try to input data:
what can I do?
Add this in your AndroidManifest.xml in your activity and this
will adjust the layout resize option.
<activity
android:name=".ActivityName"
android:windowSoftInputMode="adjustResize"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Add this Modifier to the TextField.
modifier = Modifier.navigationBarsWithImePadding(),
Refer this sample app for complete implementation.
Note
This is not a very good solution as there are a lot of caveats.
I have added this as there is no official solution and this is the code used in google code samples.
This works only if there is a single TextField on the screen. I am working with forms and this doesn't work.
The TextField must be the last view vertically.
If you add this in you Activity, worked fine for me
<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustResize"
...>
In addition to that, you can add a scroll to your screen...
I'm adding my entire test code just to illustrate.
#Composable
fun BigFormScreen() {
var text by remember {
mutableStateOf("")
}
Column(
Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
painterResource(id = R.drawable.ic_android_orange),
contentDescription = null,
modifier = Modifier.size(300.dp)
)
TextField(value = text, onValueChange = { text = it })
}
}
setContent {
ProvideWindowInsets {
JetpackComposeInsetsTheme {
Surface(
color = Color.Yellow,
modifier = Modifier.fillMaxSize()
) {
ContentView(modifier = Modifier
.navigationBarsWithImePadding())
}
}
}
}
https://google.github.io/accompanist/api/insets/insets/com.google.accompanist.insets/ime-padding.html
https://medium.com/mobile-app-development-publication/android-jetpack-compose-inset-padding-made-easy-5f156a790979
Related
I have the following code:
#Composable
internal fun ActivityInputBottomSheet() {
val items = listOf("Calories", "Steps", "Water")
var currentActive by remember {
mutableStateOf(items[0])
}
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
modifier = Modifier
.clip(CircleShape)
.background(Color.Red),
verticalAlignment = Alignment.CenterVertically
) {
items.forEach {
Text(
it,
modifier = Modifier
.clip(CircleShape)
.background(if (it == currentActive) Color.Blue else Color.Transparent)
.clickable {
currentActive = it
}
.padding(
vertical = Padding.Padding8,
horizontal = Padding.Padding16
),
color = Color.White,
)
}
}
}
}
Here I implemented a selector with 3 options (when user clicks at the one option it becomes active, and all other become inactive). It works correctly, but I want to add animation of sliding from the one option to another while changing state of selector (for example if user clicks at the first option and then at the third, blue background will slide through the first, then second and stop at third option). How can it be achieved? Thanks in advance for any help!
I'm using Scaffold for my main screen with a fixed bottomBar that is visible in every screen of the app, and I'm applying the innerPadding of the Scaffold to its content.
I want the keyboard to appear over the bottomBar, and for that I'm applying the imePadding() only to the Scaffold's content.
However, when the keyboard is opened, both the Scaffold's innerPading and imePadding() are applied to the contents padding.
I've tried to go through the Accompanist Insets migration, but no lucky.
Is there anyway that I can prevent it and apply only one or the other?
Here is a piece of my code:
Scaffold(
topBar = { },
bottomBar = { },
modifier = Modifier
.systemBarsPadding()
) { innerPadding ->
Content(
modifier = Modifier
.padding(innerPadding)
.imePadding()
)
}
And this is the result:
With the now, deprecated, Accompanist Insets, I was using the following solution:
val isImeVisible = LocalWindowInsets.current.ime.isVisible
val contentPadding = remember(isImeVisible) {
if (isImeVisible) PaddingValues(top = innerPadding.calculateTopPadding()) else innerPadding
}
According to Accompanist Insets migration, LocalWindowInsets.current.ime should be replaced with WindowInsets.ime.
It doesn't have isVisible for now, until this bug is fixed. Here's how I've re-created it for now:
val WindowInsets.Companion.isImeVisible: Boolean
#Composable
get() {
val density = LocalDensity.current
val ime = this.ime
return remember {
derivedStateOf {
ime.getBottom(density) > 0
}
}.value
}
Usage:
val isImeVisible = WindowInsets.isImeVisible
This should work with your old remember(isImeVisible) code.
Another solution would be to set BringIntoViewRequester to your content inside Scaffold. Then when textField is focused, you could call bringIntoViewRequester.bringIntoView(). This way you wouldn't need to set any paddings.
val bringIntoViewRequester = remember { BringIntoViewRequester() }
Column(
modifier = Modifier.bringIntoViewRequester(bringIntoViewRequester)
) {
TextField(
value = "",
onValueChange = {},
modifier = Modifier
.onFocusEvent {
if (it.isFocused) {
coroutineScope.launch {
delay(350)
bringIntoViewRequester.bringIntoView()
}
}
}
)
}
Try using something like this (WARNING: consumedWindowInsets is Experimental, but it's working):
Scaffold(
topBar = { },
bottomBar = { },
modifier = Modifier
.systemBarsPadding()
) { innerPadding ->
Content(
modifier = Modifier
.consumedWindowInsets(innerPadding)
.padding(innerPadding)
.imePadding()
)
}
If you focus a TextField near the bottom of the screen, keyboard appears for a moment and then immediately hides. But if you focus some TextField from above, keyboard opens as usual and you can scroll to the bottom. This happens if windowSoftInputMode is set to adjustResize. If none is set, then the behaviour goes to i would say random (keyboard may overlap content, also it may push toolbar and etc.). Perhaps i am simply doing all this wrong, i dunno. I wonder if anyone faced this issue before and could give me a hand.
Sample code (for simplicity i hold mutable states right here, not using ViewModel):
#Composable
fun Greeting() {
Scaffold(topBar = {
TopAppBar(title = { Text(text = "Some title") })
}) {
val focusManager = LocalFocusManager.current
LazyColumn(
contentPadding = PaddingValues(all = 16.dp),
verticalArrangement = Arrangement.spacedBy(space = 16.dp)
) {
items(count = 20) { index ->
val (value, onValueChange) = rememberSaveable { mutableStateOf("Some value $index") }
TextField(
value = value,
onValueChange = onValueChange,
modifier = Modifier.fillMaxWidth(),
label = { Text(text = "Some label $index") },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
keyboardActions = KeyboardActions(onNext = {
if (!focusManager.moveFocus(FocusDirection.Down))
focusManager.clearFocus()
}),
singleLine = true
)
}
}
}
}
Compose version 1.0.5
I've got a dialog where the user can select something and depending on the choice, the layout will be updated. The problem is that the height of the dialog is never updated to reflect the layout changes.
How to recompose the dialog to make the layout fit in the dialog?
Example:
#Composable
fun AlertDialogTest() {
var showDialog by remember { mutableStateOf(false)}
var showExtra by remember { mutableStateOf(false)}
Button(onClick = { showDialog = true }) {
Text("Open dialog")
}
if (showDialog) {
AlertDialog(
text = {
Column { Button(onClick = {showExtra = true}) {
Text ("Show rest of dialog")
}
if (showExtra) {
Text("More text", style = MaterialTheme.typography.h5)
Text("Even more text", style = MaterialTheme.typography.h5)
}
}
},
confirmButton = { TextButton(onClick = { showDialog = false }) {
Text("Close")
}},
onDismissRequest = {showDialog = false},
)
}
}
And the result:
I've also faced the same issue, and found the solution for a longer text or other contents in Jetpack Compose Alert Dialog
AlertDialog(
onDismissRequest = { },
properties = DialogProperties(usePlatformDefaultWidth = false),
modifier = Modifier
.padding(28.dp)
.fillMaxWidth()
.wrapContentHeight(),
title = null,
text = {
// Your alert dialog content
},confirmButton = {
TextButton(onClick = { /*TODO*/ }) {
Text(text = "OK")
}
})
It did work as expected for me in beta08. Then, after upgrate to rc02 it stopped working - popup dialogs, drop down menus (basicaly all elements that are backed by platform windows) stopped resizing properly on content size change. And indeed I've found a bug for it - https://issuetracker.google.com/issues/194911971. And for now I, sadly, haven't found a workaround, so we better wait until it's fixed.
UPD.
As is commented in aforementioned issue, there is a workaround. Check the answer here.
Another possible workaround consists in forcing recomposition of the dialogue when data changes: https://issuetracker.google.com/issues/221643630#comment8
I have a submission form interface,use ListView Component, and the row contain TextInput Component, I want to user KeyboardAvoidingView to avoid The Keyboard cover the TextInput in row , But it is not working,The row does not move up.
my code:
render() {
return (
<KeyboardAvoidingView style={styles.container} behavior='padding'>
<ListView
dataSource = {this.state.dataSource}
renderRow = {this._renderRow.bind(this)}
onEndReachedThreshold = {0}
overflow = 'hidden'
keyboardDismissMode = 'on-drag'
removeClippedSubviews = {true}
/>
</KeyboardAvoidingView>
);
}
There is one module which I have used for keyboard issue: https://github.com/APSL/react-native-keyboard-aware-scroll-view
You can use it same way:
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
render() {
return (
<KeyboardAwareScrollView extraHeight={130}>
// your code here
</KeyboardAwareScrollView>
);
}
Let me know if face any issue to use it.