android - 如何强制软输入与底部锚定视图重叠?
问题描述
TL;DR:软键盘应该与底部锚定视图重叠,而不是向上推。一个mcve的Gitlab 链接。
概括:
我有一个AppCompatDialogFragment
(androidx),它在手机上全屏显示,在平板电脑上具有固定尺寸dialog?.window?.setLayout(width, height)
(以防万一)。对话框的布局有一些内容放置在ScrollView
底部和一个类似按钮的布局中(完整的 XML 结构见下文)。
旁注:有AppCompatDialogFragment
问题的超类调用setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
它的Window
.
问题:
当软键盘由于某些文本输入接收焦点而出现时,它会将整个布局向上推,包括我希望软键盘重叠的底部锚定视图。出于某种原因,这个问题只影响手机,在平板电脑上,软键盘正确地覆盖了所有内容,包括底部锚定视图,没有任何额外的调整或标志。
我尝试过的(没有任何成功):
- 为有问题的设置
android:windowSoftInputMode="adjustNothing"
(尝试其他标志“以防万一”)Activity
,还尝试在代码中应用它们 android:isScrollContainer="false"
在 theScrollView
及其父级上设置- 以上组合
- 寻找类似的问题,并确认提出的解决方案不起作用
这是有问题的布局(注意:我省略了许多不相关的属性以保持片段大小合理;所有内容都垂直放置,与元素的顺序匹配。<include>
元素包含文本输入):
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:id="@+id/toolbar"
android:layout_height="?attr/actionBarSize"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/bottom_layout"
app:layout_constraintTop_toBottomOf="@id/toolbar"
android:isScrollContainer="false"
android:scrollbarStyle="outsideOverlay">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include
layout="@layout/some_layout_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<include
layout="@layout/some_layout_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<!-- I want this one to be overlapped by the soft input, but it's just pushed up -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/bottom_layout"
app:layout_constraintBottom_toBottomOf="parent">
<View
android:layout_width="match_parent"
android:layout_height="@dimen/divider"
android:background="@color/dark_grey" />
<TextView
android:layout_width="match_parent"
android:layout_height="@dimen/some_dimen"
android:foreground="?attr/selectableItemBackground"
android:text="@string/text" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
问题:如何强制软键盘与所有设备底部的布局重叠?
如果您需要任何其他详细信息,请发表评论。
编辑:这是一个重现问题的最小演示应用程序:https ://gitlab.com/Droidman/soft-keyboard-issue-demo
解决方案
尝试将以下行添加到onCreateView()
of DemoDialog
:
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
将此更改应用到对话框的窗口而不是活动的窗口很重要。
有了这个,这就是我在使用你的 MCVE 运行 API 29 的 Nexus 6 模拟器上看到的:
您可能需要稍微处理一下展示位置,但这应该会有所帮助。
让我们看一下引擎盖下的内容。对于手机和平板电脑,软输入模式为零onCreateView()
。此值对应于SOFT_INPUT_ADJUST_UNSPECIFIED。SOFT_INPUT_ADJUST_PAN的文档解释了当未指定软输入模式时会发生什么(重点是我的。)
softInputMode的调整选项:设置为显示输入法时有一个窗口平移,因此它不需要处理调整大小,而是由框架平移以确保当前输入焦点可见。这不能与 SOFT_INPUT_ADJUST_RESIZE 结合使用;如果这些都没有设置,那么系统将尝试根据窗口的内容选择一个或另一个。
查看onStart()
( dialog?.window?.attributes?.softInputMode
) 中软输入模式的值,系统为手机选择的值为SOFT_INPUT_ADJUST_RESIZE),为平板电脑选择的值为SOFT_INPUT_ADJUST_PAN。这解释了手机和平板电脑之间的差异。
因此,始终将软输入模式设置为SOFT_INPUT_ADJUST_PAN
看起来是最好的解决方案,尽管它SOFT_INPUT_ADJUST_NOTHING
也可以工作,并且对于某些布局可能更可取。