8

问题:

如何使用最新的 WindowInset API调整对话框和软键盘之间的空间?


我有一个带有一些 EditText 的 BottomSheetDialog。默认动画将在我的 EditText 正下方显示软键盘,它将覆盖我的保存按钮。在做了一些研究之后,我将这一行添加到我的BottomSheetDialog片段中

getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);

它起作用了(如下图所示)!

这就是我想要的

但显然SOFT_INPUT_ADJUST_RESIZE已弃用。

   * @deprecated Call {@link Window#setDecorFitsSystemWindows(boolean)} with {@code false} and
   * install an {@link OnApplyWindowInsetsListener} on your root content view that fits insets
   * of type {@link Type#ime()}.

而且我不知道如何使用 newOnApplyWindowInsetsListener来达到相同的效果。这是我当前的BottomSheetDialog片段:

public class BottomSheetDialog extends BottomSheetDialogFragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

//      Adding this line works, but it's deprecated in API 30
//      getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
      
        getDialog().getWindow().setDecorFitsSystemWindows(false);
        view = inflater.inflate(R.layout.fragment_bottom_dialog_cash, container, false);
        view.setOnApplyWindowInsetsListener((v, insets) -> {
            Log.d("dialog", "onCreateView: ");
            Insets imeInsets = insets.getInsets(WindowInsets.Type.ime());
            v.setPadding(0,0,0,imeInsets.bottom);
            return insets;
        });
        return view;
    }

我在另一个片段中使用了一个 onclicklistener 来显示这个对话框。代码在Another fragment

    @Override
    public void onItemClick(int position) {
        BottomSheetDialog dialog = new BottomSheetDialog();
        dialog.show(getParentFragmentManager(), "BottomSheetDialog");
    }

事实上,日志表明当软键盘弹出时,监听器从未被触发。仅供参考,我正在关注这个视频这个博客

4

3 回答 3

10

经过更多研究,我发现如果我使用viewBinding并替换viewbind.getRoot(),那么一切正常。我不知道为什么(也许我应该使用 inonViewCreated而不是onCreateView?)但代码应该对遇到同样问题的人有所帮助。

// NOTE: you have to set this in the activity instead of fragment.
getWindow().setDecorFitsSystemWindows(false);

// Only work with API30 or above!
bind.getRoot().setOnApplyWindowInsetsListener((v, insets) -> { 
    imeHeight = insets.getInsets(WindowInsets.Type.ime()).bottom;
    bind.getRoot().setPadding(0, 0, 0, imeHeight);
    return insets;
});

需要注意的一件事是 setDecorFitsSystemWindows(false) 意味着应用程序(您)负责所有系统窗口,包括状态栏和导航栏。

我还发现下面链接的教程非常有用,如果您想了解更多关于 windowInsets 和新动画回调的信息,请查看。

用于检查键盘 (IME) 可见性和大小的新 WindowInsets API

适用于 Android 11 的窗口插图和键盘动画教程

于 2020-12-08T06:23:23.960 回答
7

兼容版本

WindowCompat.setDecorFitsSystemWindows(window, false)
ViewCompat.setOnApplyWindowInsetsListener(rootView()) { _, insets ->
    val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
    rootView().setPadding(0, 0, 0, imeHeight)
    insets
}

或使用插入器库

 WindowCompat.setDecorFitsSystemWindows(window, false)
 rootView().applyInsetter {
        type(ime = true) {
            padding()
        }
    }
于 2021-07-01T10:45:23.180 回答
4

唯一对我有用的方法是将 BottomSheetDialog 的样式设置为使用以下内容:

<style name="BottomSheetDialogTheme" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
  <item name="android:windowIsFloating">false</item>
  <item name="android:windowSoftInputMode">adjustResize|stateVisible</item>
</style>
于 2021-02-20T01:46:42.840 回答