(Compose UI) - 键盘 (IME) 与应用内容重叠
(Compose UI) - Keyboard (IME) overlaps content of app
几天前我遇到了一个问题,我的部分视图被键盘覆盖了。
假设我们有 3 个不同的对话框(可以是任何内容),如下所示:
当我想写任何东西时,最后一个对话框被键盘覆盖:
并且无法查看用户写的内容。这是我的代码:
@Composable
fun BuildWordsView(navController: NavController, sharedViewModel: SharedViewModel) {
Column(
modifier = Modifier
.fillMaxWidth()
.background(PrimaryLight)
.fillMaxSize()
) {
BuildWordsScreenContents()
}
}
@Composable
fun BuildWordsScreenContents() {
Column(
Modifier
.fillMaxSize()
.padding(all = 16.dp)
) {
val inputBoxModifier = Modifier
.clip(RoundedCornerShape(10.dp))
.background(Primary)
.weight(12f)
.wrapContentHeight()
InputBlock("Dialog1", inputBoxModifier)
Spacer(Modifier.weight(1f))
InputBlock("Dialog2", inputBoxModifier)
Spacer(Modifier.weight(1f))
InputBlock("Dialog3", inputBoxModifier)
}
}
@Composable
fun InputBlock(dialogText: String, inputBlockModifier: Modifier) {
Column(modifier = inputBlockModifier) {
Text(
dialogText,
fontSize = 30.sp,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.wrapContentSize(Alignment.Center)
)
var text by remember { mutableStateOf("") }
TextField(
value = text,
modifier = Modifier
.fillMaxWidth()
.wrapContentSize(Alignment.Center),
onValueChange = { text = it },
label = { Text("Label") }
)
}
}
这个问题好像和我的差不多,但是答案修改了我想避免的视图内容:
现在我想出了解决这个问题的方法,我分享我的方法作为答案
我处理这个问题的方法是使用 Insets for Jetpack Compose:
https://google.github.io/accompanist/insets/
为了开始处理问题,您需要添加对 gradle 的依赖(当前版本为 0.22.0-rc)。
dependencies {
implementation "com.google.accompanist:accompanist-insets:0.22.0-rc"
}
然后你需要用 ProvideWindowInsets
将你的内容包装在你的 activity 中
setContent {
ProvideWindowInsets {
YourTheme {
//YOUR CONTENT HERE
}
}
}
此外,您需要在 activity onCreate() 函数中添加以下行:
WindowCompat.setDecorFitsSystemWindows(window, false)
更新:尽管推荐使用此功能,但根据我的经验,它可能会使此方法无效。如果遇到任何问题,您可能需要删除此行。
现在您的项目已设置为使用 Insets
在接下来的步骤中,我将使用我在问题中提供的代码
首先你需要用
包裹你的主栏
ProvideWindowInsets(windowInsetsAnimationsEnabled = true)
然后让我们稍微修改一下修饰符,添加:
.statusBarsPadding()
.navigationBarsWithImePadding()
.verticalScroll(rememberScrollState())
如您所见,我的方法中的技巧是使用 verticalScroll()。主栏的最终代码应如下所示:
@Composable
fun BuildWordsView(navController: NavController, sharedViewModel: SharedViewModel) {
ProvideWindowInsets(windowInsetsAnimationsEnabled = true) {
Column(
modifier = Modifier
.fillMaxWidth()
.background(PrimaryLight)
.statusBarsPadding()
.navigationBarsWithImePadding()
.verticalScroll(rememberScrollState())
.fillMaxSize()
) {
BuildWordsScreenContents()
}
}
}
现在修改一下fun BuildWordsScreenContents()
中Column的修饰符
主要修改是我们通过以下方式提供屏幕高度:
.height(LocalConfiguration.current.screenHeightDp.dp)
这意味着我们 Column 的高度将完美适合我们的屏幕。 因此当键盘未打开时,列将不可滚动
有完整代码:
@Composable
fun BuildWordsView(navController: NavController, sharedViewModel: SharedViewModel) {
ProvideWindowInsets(windowInsetsAnimationsEnabled = true) {
Column(
modifier = Modifier
.fillMaxWidth()
.background(PrimaryLight)
.statusBarsPadding()
.navigationBarsWithImePadding()
.verticalScroll(rememberScrollState())
.fillMaxSize()
) {
BuildWordsScreenContents()
}
}
}
@Composable
fun BuildWordsScreenContents() {
Column(
Modifier
.height(LocalConfiguration.current.screenHeightDp.dp)
.padding(all = 16.dp)
) {
val inputBoxModifier = Modifier
.clip(RoundedCornerShape(10.dp))
.background(Primary)
.weight(12f)
.wrapContentHeight()
InputBlock("Dialog1", inputBoxModifier)
Spacer(Modifier.weight(1f))
InputBlock("Dialog2", inputBoxModifier)
Spacer(Modifier.weight(1f))
InputBlock("Dialog3", inputBoxModifier)
}
}
@Composable
fun InputBlock(dialogText: String, inputBlockModifier: Modifier) {
Column(modifier = inputBlockModifier) {
Text(
dialogText,
fontSize = 30.sp,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.wrapContentSize(Alignment.Center)
)
var text by remember { mutableStateOf("") }
TextField(
value = text,
modifier = Modifier
.fillMaxWidth()
.wrapContentSize(Alignment.Center),
onValueChange = { text = it },
label = { Text("Label") }
)
}
}
最终代码允许我们向下滚动视图:
API 30-
的重要说明
对于低于 30 的 API,您需要修改 AndroidManifest.xml 文件
在 android:windowSoftInputMode="adjustResize" 才能使其正常工作。 不会 调整组件的大小,但必须使此方法起作用
清单应如下所示:
<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustResize"
请随时给我任何提示,告诉我如何改进我的问题。据我所知,这个问题与 android 一样古老,我想创建一个快速教程来管理它。编码愉快!
几天前我遇到了一个问题,我的部分视图被键盘覆盖了。
假设我们有 3 个不同的对话框(可以是任何内容),如下所示:
当我想写任何东西时,最后一个对话框被键盘覆盖:
并且无法查看用户写的内容。这是我的代码:
@Composable
fun BuildWordsView(navController: NavController, sharedViewModel: SharedViewModel) {
Column(
modifier = Modifier
.fillMaxWidth()
.background(PrimaryLight)
.fillMaxSize()
) {
BuildWordsScreenContents()
}
}
@Composable
fun BuildWordsScreenContents() {
Column(
Modifier
.fillMaxSize()
.padding(all = 16.dp)
) {
val inputBoxModifier = Modifier
.clip(RoundedCornerShape(10.dp))
.background(Primary)
.weight(12f)
.wrapContentHeight()
InputBlock("Dialog1", inputBoxModifier)
Spacer(Modifier.weight(1f))
InputBlock("Dialog2", inputBoxModifier)
Spacer(Modifier.weight(1f))
InputBlock("Dialog3", inputBoxModifier)
}
}
@Composable
fun InputBlock(dialogText: String, inputBlockModifier: Modifier) {
Column(modifier = inputBlockModifier) {
Text(
dialogText,
fontSize = 30.sp,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.wrapContentSize(Alignment.Center)
)
var text by remember { mutableStateOf("") }
TextField(
value = text,
modifier = Modifier
.fillMaxWidth()
.wrapContentSize(Alignment.Center),
onValueChange = { text = it },
label = { Text("Label") }
)
}
}
这个问题好像和我的差不多,但是答案修改了我想避免的视图内容:
现在我想出了解决这个问题的方法,我分享我的方法作为答案
我处理这个问题的方法是使用 Insets for Jetpack Compose:
https://google.github.io/accompanist/insets/
为了开始处理问题,您需要添加对 gradle 的依赖(当前版本为 0.22.0-rc)。
dependencies {
implementation "com.google.accompanist:accompanist-insets:0.22.0-rc"
}
然后你需要用 ProvideWindowInsets
setContent {
ProvideWindowInsets {
YourTheme {
//YOUR CONTENT HERE
}
}
}
此外,您需要在 activity onCreate() 函数中添加以下行:
WindowCompat.setDecorFitsSystemWindows(window, false)
更新:尽管推荐使用此功能,但根据我的经验,它可能会使此方法无效。如果遇到任何问题,您可能需要删除此行。
现在您的项目已设置为使用 Insets
在接下来的步骤中,我将使用我在问题中提供的代码
首先你需要用
包裹你的主栏ProvideWindowInsets(windowInsetsAnimationsEnabled = true)
然后让我们稍微修改一下修饰符,添加:
.statusBarsPadding()
.navigationBarsWithImePadding()
.verticalScroll(rememberScrollState())
如您所见,我的方法中的技巧是使用 verticalScroll()。主栏的最终代码应如下所示:
@Composable
fun BuildWordsView(navController: NavController, sharedViewModel: SharedViewModel) {
ProvideWindowInsets(windowInsetsAnimationsEnabled = true) {
Column(
modifier = Modifier
.fillMaxWidth()
.background(PrimaryLight)
.statusBarsPadding()
.navigationBarsWithImePadding()
.verticalScroll(rememberScrollState())
.fillMaxSize()
) {
BuildWordsScreenContents()
}
}
}
现在修改一下fun BuildWordsScreenContents()
主要修改是我们通过以下方式提供屏幕高度:
.height(LocalConfiguration.current.screenHeightDp.dp)
这意味着我们 Column 的高度将完美适合我们的屏幕。 因此当键盘未打开时,列将不可滚动
有完整代码:
@Composable
fun BuildWordsView(navController: NavController, sharedViewModel: SharedViewModel) {
ProvideWindowInsets(windowInsetsAnimationsEnabled = true) {
Column(
modifier = Modifier
.fillMaxWidth()
.background(PrimaryLight)
.statusBarsPadding()
.navigationBarsWithImePadding()
.verticalScroll(rememberScrollState())
.fillMaxSize()
) {
BuildWordsScreenContents()
}
}
}
@Composable
fun BuildWordsScreenContents() {
Column(
Modifier
.height(LocalConfiguration.current.screenHeightDp.dp)
.padding(all = 16.dp)
) {
val inputBoxModifier = Modifier
.clip(RoundedCornerShape(10.dp))
.background(Primary)
.weight(12f)
.wrapContentHeight()
InputBlock("Dialog1", inputBoxModifier)
Spacer(Modifier.weight(1f))
InputBlock("Dialog2", inputBoxModifier)
Spacer(Modifier.weight(1f))
InputBlock("Dialog3", inputBoxModifier)
}
}
@Composable
fun InputBlock(dialogText: String, inputBlockModifier: Modifier) {
Column(modifier = inputBlockModifier) {
Text(
dialogText,
fontSize = 30.sp,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.wrapContentSize(Alignment.Center)
)
var text by remember { mutableStateOf("") }
TextField(
value = text,
modifier = Modifier
.fillMaxWidth()
.wrapContentSize(Alignment.Center),
onValueChange = { text = it },
label = { Text("Label") }
)
}
}
最终代码允许我们向下滚动视图:
API 30-
的重要说明对于低于 30 的 API,您需要修改 AndroidManifest.xml 文件
在
清单应如下所示:
<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustResize"
请随时给我任何提示,告诉我如何改进我的问题。据我所知,这个问题与 android 一样古老,我想创建一个快速教程来管理它。编码愉快!