在状态栏下方显示DialogFragment内容

13

我试图显示一个有着匹配父布局高度和宽度的 DialogFragment,但是发现在顶部该DialogFragment被显示在StatusBar下面。

这个DialogFragment会使用一些默认的内边距(bottom, right, left, and top)。但是顶部内边距应该从StatusBar开始计算而不是整个屏幕大小。

如何设置DialogFragment以使其匹配父布局,但顶部,底部,右侧和左侧均具有正常/默认的内边距?

2个回答

26

默认情况下,Dialog将应用 FLAG_LAYOUT_IN_SCREENFLAG_LAYOUT_INSET_DECOR 标志。以下是来自 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是一个标志,你不想被应用。来自文档

窗口标志:仅在与FLAG_LAYOUT_IN_SCREEN结合使用时才有特殊选项。当请求在屏幕中的布局时,您的窗口可能出现在屏幕装饰(例如状态栏)的顶部或后面。通过同时包括此标志,窗口管理器将报告所需的插入矩形,以确保您的内容不被屏幕装饰物覆盖。这个标志通常由Window设置,如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>

这将是输出结果:

您可以在我的这个答案中看到那个标志的含义。


将其添加到onResume()中并不能解决问题。现在我有视图包裹高度和宽度。 - Bugdr0id
你是否正在执行 getDialog().getWindow().setFlags(...) - azizbekian
1
是的,我正在设置:getDialog().getWindow().setFlags(FLAG_LAYOUT_IN_SCREEN, FLAG_LAYOUT_IN_SCREEN); - Bugdr0id
我觉得我误解了你的问题。"如何将DialogFragment设置为match_parent,但在顶部、底部、右侧和左侧具有正常/默认填充?" 你想要什么填充? - azizbekian
您所发布的图片显示了我的问题:D 我想避免我的对话框出现在状态栏下方。 - Bugdr0id
1
我无法让DialogFragment被透明或半透明的状态栏覆盖... - YuTang

-1

对我来说,被接受的答案(@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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接