9

我有一个使用 Fragments 制作的 Android 应用程序

我使用以下代码隐藏了屏幕顶部和底部的栏。

 @Override
protected void onResume() {
    super.onResume();
    isInBackground = false;

    if(null == getFragmentManager().findFragmentById(R.id.content_container))
    {
        getFragmentManager().beginTransaction().add(R.id.content_container,new PresenterFragment(), PresenterFragment.FRAG_TAG).commit();
    }

    if(Build.VERSION.SDK_INT >=19)
    {
        View decorView = getWindow().getDecorView();
        int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
        decorView.setSystemUiVisibility(uiOptions);
        decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
            @Override
            public void onSystemUiVisibilityChange(int visibility) {
                View decorView = getWindow().getDecorView();
                int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                        | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
                decorView.setSystemUiVisibility(uiOptions);
            }
        });
    }
}

当显示条形的软键盘时,我可以忍受这一点,因为当键盘被关闭时它们会隐藏起来。但是,如果在显示软键盘时显示对话框片段,那么当键盘和对话框片段都被关闭时,它们会出现条形图保持在应用程序的顶部。

我的3个问题是

是否可以停止软键盘以更改 UI 模式?

是否可以通过更改 UI 模式来阻止 DialogsFraments 的显示?

编辑:我曾经在下面的代码中查看是否显示了键盘

public static boolean isKeyBoardShown(){
    InputMethodManager imm = (InputMethodManager)currentActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
    if (imm.isAcceptingText()) {
        return true;
    } else {
        return false;
    }
}

-> 我知道活动中的对话框可以解决,但我看不到或修改代码以在 DialogFragment 中工作

如果两者都不可能,为什么当同时显示键盘和 DialogFrament 时应用程序会卡在错误的 UI 模式?

4

5 回答 5

33

1.解法说明。

我从 android api 文档中引用了以下引号。

使用沉浸式全屏模式

启用沉浸式全屏模式后,您的 Activity 将继续接收所有触摸事件。用户可以通过沿着系统栏通常出现的区域向内滑动来显示系统栏。这将清除 SYSTEM_UI_FLAG_HIDE_NAVIGATION 标志(以及 SYSTEM_UI_FLAG_FULLSCREEN 标志,如果应用的话),因此系统栏变得可见。如果设置,这也会触发您的 View.OnSystemUiVisibilityChangeListener。

OnSystemUiVisibilityChangeListener首先,使用粘性沉浸时不需要。

但是,如果您希望系统栏在片刻后再次自动隐藏,则可以改用 SYSTEM_UI_FLAG_IMMERSIVE_STICKY 标志。请注意,标志的“粘性”版本不会触发任何侦听器,因为在此模式下临时显示的系统栏处于瞬态状态。

使用粘性/非粘性浸泡的建议:

如果您正在构建一个真正身临其境的应用程序,您希望用户在屏幕边缘附近进行交互,并且您不希望他们需要频繁访问系统 UI,请将 IMMERSIVE_STICKY 标志与 SYSTEM_UI_FLAG_FULLSCREEN 和 SYSTEM_UI_FLAG_HIDE_NAVIGATION 结合使用。例如,这种方法可能适用于游戏或绘图应用程序。

但是,您提到用户需要键盘,所以我建议这样做:
使用非粘性沉浸式

如果您正在构建书籍阅读器、新闻阅读器或杂志,请将 IMMERSIVE 标志与 SYSTEM_UI_FLAG_FULLSCREEN 和 SYSTEM_UI_FLAG_HIDE_NAVIGATION 结合使用。因为用户可能希望稍微频繁地访问操作栏和其他 UI 控件,但又不想在翻阅内容时被任何 UI 元素打扰,所以 IMMERSIVE 是此用例的一个不错的选择。


2.解决方案

我的解决方案是在片段的 onActivityCreated 中设置您的视图 ui。

我的示例取自ImmersiveModeFragment.java示例。

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    final View decorView = getActivity().getWindow().getDecorView();
    decorView.setOnSystemUiVisibilityChangeListener(
            new View.OnSystemUiVisibilityChangeListener() {
                @Override
                public void onSystemUiVisibilityChange(int i) {
                    hideSystemUI();
                }
            });
}

创建一个单独的方法来管理您从您的OnSystemUiVisibilityChangeListener()

取自这里非粘性浸泡

private void hideSystemUI() {
    // Set the IMMERSIVE flag.
    // Set the content to appear under the system bars so that the content
    // doesn't resize when the system bars hide and show.
    mDecorView.setSystemUiVisibility(
        View.SYSTEM_UI_FLAG_LAYOUT_STABLE
        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
        | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
        | View.SYSTEM_UI_FLAG_IMMERSIVE);
}

然后您可以再次调用此方法onResume

onResume(){
    hideSystemUI();
}

3. 替代解决方案。

如果粘性沉浸是你真正想要的,你需要尝试不同的方法。

用于粘性浸泡

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        decorView.setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_FULLSCREEN
            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);}
}

我希望这能解决你的问题。

于 2015-10-03T16:57:16.773 回答
4

我知道这已经过时了,但我为此苦苦挣扎了一段时间,因为我有 dialogFragments 和我的 navigationView 中的下拉菜单,它不断地显示系统 UI。以下是我所做的最终工作的事情(前两件我发现了很多地方):

在我AndroidManifest.xml的申请中

android:theme="@style/AppTheme.NoActionBar"

在我的活动中

View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
decorView.setSystemUiVisibility(uiOptions);

最终成为我的关键的是我的styles.xml

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowFullscreen">true</item>
    </style>
</resources>
于 2019-01-12T07:41:58.333 回答
2

是否可以停止软键盘以更改 UI 模式?

也许

是否可以通过更改 UI 模式来阻止 DialogsFraments 的显示?

是的,只要您尝试了解自己在做什么

如果两者都不可能,为什么当同时显示键盘和 DialogFrament 时应用程序会卡在错误的 UI 模式?

因为问题2的答案

现在这是您的整体解决方案

当前/焦点视图是操作系统从中获取 UI 可见性设置的对象,当视图被遮挡或相对于 z 顺序不在顶部时,则将setSystemUiVisibility()其设置为默认值。所以改为尝试破解

View decorView = getWindow().getCurrentFocus() != null ? 
                getWindow().getCurrentFocus() :getWindow().getDecorView();

每当您DialogFragment被解雇时,请检查上述行并重新调用您的可访问性 ui 代码;因为....猜测到此为止很清楚

于 2015-09-30T02:58:19.930 回答
2

在 Dialog 或 BottomSheetDialogFragment 中,您必须实施这个对我有用的解决方案。

第1步:

在您的对话框或 BottomSheetDialog 中,在 onActivityCreated 方法中编写此代码,

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
var viewParent = view
while (viewParent is View) {
    viewParent.fitsSystemWindows = false
    viewParent.setOnApplyWindowInsetsListener { _, insets -> insets }
    viewParent = viewParent.parent as View?
 }
}

第2步:另外,覆盖以下方法:

override fun setupDialog(dialog: Dialog, style: Int) {
super.setupDialog(dialog, style)
dialog?.window?.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)

}

现在看看魔法:)

于 2020-01-13T12:39:44.683 回答
1

此修复程序以及与软键盘相关的另一个修复程序包含在DialogFragment此库的类中。只需扩展它而不是标准库:

https://github.com/marksalpeter/contract-fragment

该库的主要目的是为利用父/子片段关系的片段和对话框片段添加委托功能,但您可以只使用错误修复或复制/粘贴文件

于 2018-02-14T00:08:17.517 回答