【问题标题】:(Compose UI) - Keyboard (IME) overlaps content of app(撰写 UI)- 键盘 (IME) 与应用程序的内容重叠
【发布时间】:2022-01-05 17:46:45
【问题描述】:

几天前我遇到了一个问题,我的一部分视图被键盘重叠。

假设我们有 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") }
        )
    }
}

这个问题似乎与我的相似,但答案会修改我想要避免的视图内容:

Software keyboard overlaps content of jetpack compose view

现在我想出了如何解决这个问题,并分享我的方法作为答案

【问题讨论】:

  • 您不应仅仅因为当前答案不适合您而创建其他问题。你应该在那里留下你自己的答案。
  • @PhilipDukhov 它没有回答我的问题,我提到了它。请仔细阅读我的问题。主要区别在于我不想创建可滚动布局,而是保持原样(但是我将其用作技巧)。此外,在我看来,我没有显示任何列表。那是完全不同的问题
  • 它并没有真正的区别,你的答案没有在this answer 或伴奏文档中提到。另外,如果您必须使用可滚动,那么您一开始没有使用它有什么不同?任何正在寻找答案的人都会通过原始标题找到它,并且将有完整的信息来解决它。

标签: android android-layout android-jetpack-compose jetpack-compose-accompanist


【解决方案1】:

我处理这个问题的方法是使用 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
        }
    }
}

另外,您需要在您的活动 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"

请随时给我任何提示,我可以如何改进我的问题。 AFAIK 这个问题和 android 一样古老,我想创建一个快速教程来管理它。编码愉快!

【讨论】:

  • 你正在使用 fillMaxWidth() 和 fillMaxSize() 我想你忘了删除 fillMaxWidth()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-25
  • 1970-01-01
  • 2015-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多