如何使底部对话框(bottomSheetDialog)覆盖状态栏并全屏显示?

20

我最近使用了android.support.design.widget.BottomSheetDialogFragment。我想做类似于Google联系人应用程序的事情,即它的BottomSheet可以覆盖工具栏和状态栏。但是,当我使用BottomSheetDialogFragment来实现这一点时,结果是这样的:

My Implementation

你可以看到活动的工具栏仍然可见。这是我的BottomSheetDialogFragment代码:

public class KeyDetailFragment extends BottomSheetDialogFragment {
    private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {
        @Override
        public void onStateChanged(@NonNull View bottomSheet, int newState) {
            if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                dismiss();
            }
        }

        @Override
        public void onSlide(@NonNull View bottomSheet, float slideOffset) {

        }
    };

    @Override
    public void setupDialog(Dialog dialog, int style) {
        super.setupDialog(dialog, style);
        View contentView = View.inflate(getActivity(), R.layout.sheet_key, null);
        dialog.setContentView(contentView);
        View parent = (View) contentView.getParent();
        parent.setFitsSystemWindows(true);
        BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(parent);
        contentView.measure(0, 0);
bottomSheetBehavior.setPeekHeight(contentView.getMeasuredHeight());

        CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) parent.getLayoutParams();
        if (params.getBehavior() instanceof BottomSheetBehavior) {
                 ((BottomSheetBehavior)params.getBehavior()).setBottomSheetCallback(mBottomSheetBehaviorCallback);
        }
        params.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
        parent.setLayoutParams(params);
    }
}

我查阅了资料并发现一个引起我兴趣的属性:

private static int getThemeResId(Context context, int themeId) {
    if (themeId == 0) {
        // If the provided theme is 0, then retrieve the dialogTheme from our theme
        TypedValue outValue = new TypedValue();
        if (context.getTheme().resolveAttribute(
                R.attr.bottomSheetDialogTheme, outValue, true)) {
            themeId = outValue.resourceId;
        } else {
            // bottomSheetDialogTheme is not provided; we default to our light theme
            themeId = R.style.Theme_Design_Light_BottomSheetDialog;
        }
    }
    return themeId;
}

这里的属性 bottomSheetDialogTheme 可能会更改底部菜单的样式,但我不知道如何更改它,而且我怀疑这是否有效。有人能给我一个解决方案吗?使其可以覆盖工具栏和状态栏。


同样的问题,你找到任何解决方案了吗? - nipun.birla
@nipun.birla 没有,虽然已经过去了大约3个月,但我还没有找到它。 - Jian Guo
我认为原因是高度问题。请查看此链接:https://dev59.com/dVsV5IYBdhLWcg3w2h4s。 - Alexander Skvortsov
我也遇到了同样的问题,但是找不到一个好的解决方案。 - Sree...
试着阅读这篇文章,它对我帮助很大。 - Shvedkov Ivan
3个回答

21

试试这个。对我有效。

@Override
public void setupDialog(Dialog dialog, int style) {
    super.setupDialog(dialog, style);
    View inflatedView = View.inflate(getContext(), R.layout.fragment_coupon, null);
    dialog.setContentView(inflatedView);


    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) inflatedView.getParent()).getLayoutParams();
    CoordinatorLayout.Behavior behavior = params.getBehavior();

    if (behavior != null && behavior instanceof BottomSheetBehavior) {
        ((BottomSheetBehavior) behavior).setBottomSheetCallback(mBottomSheetBehaviorCallback);
    }

    View parent = (View) inflatedView.getParent();
    parent.setFitsSystemWindows(true);
    BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(parent);
    inflatedView.measure(0, 0);
    DisplayMetrics displaymetrics = new DisplayMetrics();        getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
    int screenHeight = displaymetrics.heightPixels;
    bottomSheetBehavior.setPeekHeight(screenHeight);

    if (params.getBehavior() instanceof BottomSheetBehavior) {
        ((BottomSheetBehavior)params.getBehavior()).setBottomSheetCallback(mBottomSheetBehaviorCallback);
    }

    params.height = screenHeight;
    parent.setLayoutParams(params);
}

1
需要注意的是,使用这种解决方案时,displayMetrics.heightPixels将包括通知栏高度,因此底部会被切掉一点。我使用这个方法来计算通知栏的高度。private int getStatusBarHeight() { Rect rectangle = new Rect(); Window window = getActivity().getWindow(); window.getDecorView().getWindowVisibleDisplayFrame(rectangle); return rectangle.top; } - C Nick
DisplayMetrics displaymetrics = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);转换为:DisplayMetrics displaymetrics = getActivity().getResources().getDisplayMetrics() - roghayeh hosseini
在XML中使用协调布局和应用栏能够处理它吗? - Mahdi

2

给定的参考肯定是我目的的另一种方式,添加背景阴影确实很棘手。 - Jian Guo
这个回答完全没有解决这个问题,即“使bottomSheetDialog覆盖状态栏并全屏显示”。那篇文章中没有任何有助于解决这个问题的内容,只是浪费了我点击进去的时间。此外,在SO上粘贴链接而不尝试在此处展示答案是一种不好的做法。 - Vin Norman

1
这对我来说是最简单的方法,只需扩展BottomSheetDialog并将BottomSheetBehavior设置为BottomSheetBehavior.STATE_EXPANDED
一个小技巧是使用布局名称android.support.design.R.id.design_bottom_sheet,该名称来自Android支持设计库。
class BottomSheetDialogExpanded(context: Context) : BottomSheetDialog(context) {

    private lateinit var mBehavior: BottomSheetBehavior<FrameLayout>

    override fun setContentView(view: View) {
        super.setContentView(view)
        val bottomSheet = window.decorView.findViewById<View>(android.support.design.R.id.design_bottom_sheet) as FrameLayout
        mBehavior = BottomSheetBehavior.from(bottomSheet)
        mBehavior.state = BottomSheetBehavior.STATE_EXPANDED
    }

    override fun onStart() {
        super.onStart()
        mBehavior.state = BottomSheetBehavior.STATE_EXPANDED
    }
}

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