在状态栏下方显示 DialogFragment 内容

Display DialogFragment content below status bar

我正在尝试显示高度和宽度都为 match_parent 的 DialogFragment,但碰巧 DialogFragment 显示在 StatusBar 下方。

DialogFragment 正在为底部、右侧、左侧和顶部的填充应用一些默认值。但是顶部填充应该从 statusBar 开始计算,而不是从总屏幕尺寸开始。

如何将 DialogFragment 设置为 match_parent,但在顶部、底部、右侧、左侧有 normal/default 填充?

默认情况下会应用 Dialog FLAG_LAYOUT_IN_SCREEN and FLAG_LAYOUT_INSET_DECOR flags. An excerpt from PhoneWindow:


        mIsFloating = a.getBoolean(R.styleable.Window_windowIsFloating, false);
        int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
                & (~getForcedWindowFlags());
        if (mIsFloating) {
            setLayout(WRAP_CONTENT, WRAP_CONTENT);
            setFlags(0, flagsToUpdate);
        } else {
            setFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR, flagsToUpdate);
        }

FLAG_LAYOUT_INSET_DECOR is the flag, that you do not want to be applied. From docs:

Window flag: a special option only for use in combination with FLAG_LAYOUT_IN_SCREEN. When requesting layout in the screen your window may appear on top of or behind screen decorations such as the status bar. By also including this flag, the window manager will report the inset rectangle needed to ensure your content is not covered by screen decorations. This flag is normally set for you by Window as described in setFlags(int, int).

默认情况下,windowIsFloating 已启用。因此,如果您声明自定义主题:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    ...
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>

</style>

<style name="MyTheme" parent="@style/ThemeOverlay.AppCompat.Dialog.Alert">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:colorBackgroundCacheHint">@null</item>
    <item name="android:windowFrame">@null</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowAnimationStyle">@null</item>
    <item name="android:windowIsFloating">false</item>
    <item name="android:backgroundDimEnabled">false</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowNoTitle">true</item>
</style>

然后在你的 DialogFragment:


    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = new Dialog(getActivity(), R.style.MyTheme);
        dialog.setContentView(R.layout.your_layout);
        return dialog;
    }

布局内容如下:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <View
        android:layout_gravity="center_horizontal"
        android:background="@color/colorAccent"
        android:layout_width="250dp"
        android:layout_height="700dp"/>

</FrameLayout>

然后你会得到这个输出:


如果您希望粉红色布局位于状态栏下方和导航栏上方,则只需将 android:fitsSystemWindows="true" 应用到您的根 ViewGroup:

<FrameLayout
    ...
    android:fitsSystemWindows="true">

    <View .../>

</FrameLayout>

这将是输出:

你可以在我的 回答中看到那个标志的含义。

已接受的答案 (@azizbekian) 对我来说还不够,我还需要将其应用于对话框 (onCreateDialog):

window?.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)

或者如果你想在状态栏下方但在导航栏上方:

window.decorView.systemUiVisibility =
window.decorView.systemUiVisibility or
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
 
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window.statusBarColor = Color.TRANSPARENT