英文:
How to prevent a gap between the keyboard and a bottom-aligned button in Android Jetpack Compose?
问题
你可以尝试在你的代码中使用Modifier.fillMaxHeight()
来确保按钮始终位于屏幕底部,并且在键盘打开时与键盘一起上移,关闭时下移。在以下的代码片段中,我已经添加了这个修饰符:
Column(
modifier = Modifier
.fillMaxSize()
.imePadding()
.semantics { contentDescription = screenDescription },
verticalArrangement = Arrangement.SpaceBetween,
horizontalAlignment = Alignment.CenterHorizontally
) {
// ... 省略其余的代码
Column(
modifier = Modifier
.weight(0.20f, fill = true)
.fillMaxWidth()
.fillMaxHeight() // 这里添加了Modifier.fillMaxHeight()
) {
Crossfade(targetState = isInError, label = "isInErrorButton") { isInError ->
Button(
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
shape = RectangleShape,
colors = if (isInError) {
ButtonDefaults.buttonColors(containerColor = Color.Red)
} else {
ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary)
},
onClick = {
hapticGenerator.performHapticFeedback(HapticFeedbackType.LongPress)
if (validateInput()) {
focusManager.clearFocus()
onContinueButtonClick()
navigateToNextScreen()
}
}
) {
Text(
modifier = Modifier.padding(horizontal = 16.dp),
text = "Continue",
style = MaterialTheme.typography.bodyLarge
)
}
}
}
}
这个修饰符应该帮助你解决键盘打开和关闭时出现的间隙问题。希望这对你有所帮助!
英文:
I want to have a button that is always at the bottom of the screen, when the keyboard opens it should go up with it and when it closes the button should go down again.
I tried different ways, with a Box wrapping everything and different configurations of nested Columns.
But sometimes after closing and opening the keyboard there is a gap between the keyboard and the button.
How do I fix that?
This is my current code:
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun PlayerNameSelectionScreenContent(
playerName: TextFieldValue,
onChangePlayerName: (TextFieldValue) -> Unit = {},
onContinueButtonClick: () -> Unit = {},
navigateToNextScreen: () -> Unit = {},
validateInput: () -> Boolean = { false },
isInError: Boolean = false,
errorMessage: String = ""
) {
val focusManager = LocalFocusManager.current
val focusRequester = remember { FocusRequester() }
val hapticGenerator = LocalHapticFeedback.current
val screenDescription = "Player Name Selection Screen"
Column(
modifier = Modifier
.fillMaxSize()
.imePadding()
.semantics { contentDescription = screenDescription },
verticalArrangement = Arrangement.SpaceBetween,
horizontalAlignment = Alignment.CenterHorizontally
) {
Column(
modifier = Modifier
.weight(0.40f, true)
.fillMaxWidth(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.size(32.dp))
Text(
text = "Player Setup",
style = MaterialTheme.typography.displayMedium,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.size(16.dp))
Text(
text = "Player 1",
style = MaterialTheme.typography.headlineLarge,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.size(8.dp))
Text(
text = "Start with yourself and proceed in storm order.",
style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center
)
}
Column(
modifier = Modifier
.weight(0.40f)
.fillMaxWidth(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.size(64.dp))
Text(
text = "Set the player name:",
style = MaterialTheme.typography.headlineSmall,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.size(16.dp))
val textFieldDescription = "Player name text field"
OutlinedTextField(
modifier = Modifier
.focusRequester(focusRequester)
.semantics {
contentDescription = textFieldDescription
setText { text ->
onChangePlayerName(TextFieldValue(text.text))
true
}
testTag = "PlayerName"
testTagsAsResourceId = true
},
value = playerName,
onValueChange = onChangePlayerName,
label = { Text(stringResource(id = R.string.name_text)) },
placeholder = { Text(stringResource(id = R.string.name_text)) },
singleLine = true,
isError = isInError,
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Done,
keyboardType = KeyboardType.Text
)
)
Spacer(modifier = Modifier.size(8.dp))
val errorMessageDescription =
stringResource(id = R.string.error_message_description)
Crossfade(targetState = isInError, label = "isInErrorText") { isInError ->
Text(
modifier = Modifier.semantics {
contentDescription = errorMessageDescription
},
text = if (isInError) errorMessage else "",
style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center,
color = Color.Red,
minLines = 2
)
}
}
Column(
modifier = Modifier
.weight(weight = 0.20f, fill = true)
.fillMaxWidth(),
verticalArrangement = Arrangement.Bottom
) {
Crossfade(targetState = isInError, label = "isInErrorButton") { isInError ->
Button(
modifier = Modifier
.fillMaxWidth()
.height(48.dp),
shape = RectangleShape,
colors = if (isInError) {
ButtonDefaults.buttonColors(containerColor = Color.Red)
} else {
ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary)
},
onClick = {
hapticGenerator.performHapticFeedback(HapticFeedbackType.LongPress)
if (validateInput()) {
focusManager.clearFocus()
onContinueButtonClick()
navigateToNextScreen()
}
}
) {
Text(
modifier = Modifier.padding(horizontal = 16.dp),
text = "Continue",
style = MaterialTheme.typography.bodyLarge
)
}
}
}
}
LaunchedEffect(key1 = Unit) {
focusRequester.requestFocus()
onChangePlayerName(TextFieldValue(playerName.text, TextRange(playerName.text.length)))
}
}
Here is how it looks:
Screen Screenshot
And here is a gif that shows what happens if I open and close the keyboard:
Open Keyboard Gif
I tried wrapping everything with a box that has the modifier fillMaxSize and then a Column in it with Arrangement.Bottom in that configuration the gap between the keyboard and button could appear.
Then I tried a few different configurations of the mentioned code with different nestings of the Columns.
I also tried adding or removing the imePadding modifier on the different Boxes or Columns.
答案1
得分: 0
我已经尝试了一些并且认为我找到了一个解决方案:
- 我已经在AndroidManifest.xml文件的activity部分中添加了android:windowSoftInputMode="adjustResize"。
<activity
android:name="..."
android:windowSoftInputMode="adjustResize"
...
</activity>
- 我有三列,我在前两列中添加了修饰符".weight(0.50f)",并从最后一列中移除了weight修饰符。
英文:
I have tried a bit more and think I found a solution:
- I have added android:windowSoftInputMode="adjustResize" to the activity section in the AndroidManifest.xml.
<activity
android:name="..."
android:windowSoftInputMode="adjustResize"
...
</activity>
- I have three columns, I added the modifier
.weight(0.50f)
to the first two columns and removed the weight modifier from the last column.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论