Android 如何设置BottomSheetDialogFragment的最大宽度

Android 如何设置BottomSheetDialogFragment的最大宽度,android,android-layout,bottom-sheet,Android,Android Layout,Bottom Sheet,问题 我正在使用BottomSheetDialogFragment作为我的模式底部工作表,并希望设置最大宽度,以便在平板电脑/大屏幕上底部工作表不会占据整个屏幕宽度。我如何解决这个问题?谢谢 相关代码和资源 fragment_bottomsheet.xml: res/values/styles.xml: 匹配父项 匹配父项 水平中心 res/values-w600dp/styles.xml: 匹配父项 640dp 水平中心 我找到了一个适合我的解决方案: @Override publi

问题

我正在使用
BottomSheetDialogFragment
作为我的模式底部工作表,并希望设置最大宽度,以便在平板电脑/大屏幕上
底部工作表
不会占据整个屏幕宽度。我如何解决这个问题?谢谢

相关代码和资源

fragment_bottomsheet.xml:


res/values/styles.xml:


匹配父项
匹配父项
水平中心
res/values-w600dp/styles.xml:


匹配父项
640dp
水平中心

我找到了一个适合我的解决方案:

@Override
public void onResume() {
    super.onResume();

    // Resize bottom sheet dialog so it doesn't span the entire width past a particular measurement
    WindowManager wm = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    DisplayMetrics metrics = new DisplayMetrics();
    display.getMetrics(metrics);
    int width = metrics.widthPixels < 1280 ? metrics.widthPixels : 1280;
    int height = -1; // MATCH_PARENT
    getDialog().getWindow().setLayout(width, height);
}
@覆盖
恢复时公开作废(){
super.onResume();
//调整“底部图纸”对话框的大小,使其不会跨越超过特定测量值的整个宽度
WindowManager wm=(WindowManager)getActivity().getSystemService(Context.WINDOW\u服务);
Display Display=wm.getDefaultDisplay();
DisplayMetrics=新的DisplayMetrics();
display.getMetrics(metrics);
int width=metrics.widthPixels<1280?metrics.widthPixels:1280;
int height=-1;//匹配父项
getDialog().getWindow().setLayout(宽度、高度);
}

基本上,这允许我根据显示动态地指定
底页的尺寸

正如您所提到的,BottomSheetDialogFragment似乎不尊重“wrap_content”(它总是在宽度上与父视图匹配,即使它包含的所有视图的宽度都是“wrap_content”)。我发现对我来说,最好的解决办法是利用OnGlobalYoutListener在适当的时间来调整宽度。例如:

 @Override
public void setupDialog(final Dialog dialog, int style) {
    super.setupDialog(dialog, style);
    View v = View.inflate(getActivity(), R.layout.my_bottom_sheet, null);
    View viewWithGreatestWidth = v.findViewById(R.id.my_super_wide_view);
    // Your view setup code goes here ....

    if(getResources().getBoolean(R.bool.isTablet)) {
        v.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    v.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                } else {
                    v.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                }

                // Can also just use your own preset "max width" value here;
                // This code just lets you fake "wrap_content" value
                getDialog().getWindow().setLayout(viewWithGreatestWidth.getMeasuredWidth(), WindowManager.LayoutParams.WRAP_CONTENT);
            }
        });
    }

    dialog.setContentView(v);
}

OP答案的变化,考虑到设备的像素密度和方向:

公共最终类MyBottomSheetDialogFragment扩展了BottomSheetDialogFragment{
...
专用静态int-dpToPx(int-dp){
// https://developer.android.com/guide/practices/screens_support.html#dips-贝利
float density=Resources.getSystem().getDisplayMetrics().density;
返回(int)((dp*密度)+0.5f);
}
@凌驾
恢复时公开作废(){
super.onResume();
配置配置=getActivity().getResources().getConfiguration();
如果(configuration.orientation==configuration.orientation\u)&&
配置(屏幕宽度DP>450){
//您可以更进一步,根据屏幕宽度改变底部纸张的宽度
//见有关建议https://material.io/components/sheets-bottom#specs
getDialog().getWindow().setLayout(ViewUtils.dpToPx(450),-1);
}
}
}

您可以更改nestedscrollview的尺寸以更改底部页面的尺寸。我在布局中不使用
nestedscrollview
。请注意,
widthPixels
不是测量屏幕宽度的最佳方法,因为不同的屏幕具有不同的像素密度。最好在
dp
中检查宽度,而不是
px
。见下面我的答案。
<style name="BottomSheetStyle">
    <item name="android:layout_height">match_parent</item>
    <item name="android:layout_width">640dp</item>
    <item name="android:layout_gravity">center_horizontal</item>
</style>
@Override
public void onResume() {
    super.onResume();

    // Resize bottom sheet dialog so it doesn't span the entire width past a particular measurement
    WindowManager wm = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    DisplayMetrics metrics = new DisplayMetrics();
    display.getMetrics(metrics);
    int width = metrics.widthPixels < 1280 ? metrics.widthPixels : 1280;
    int height = -1; // MATCH_PARENT
    getDialog().getWindow().setLayout(width, height);
}
 @Override
public void setupDialog(final Dialog dialog, int style) {
    super.setupDialog(dialog, style);
    View v = View.inflate(getActivity(), R.layout.my_bottom_sheet, null);
    View viewWithGreatestWidth = v.findViewById(R.id.my_super_wide_view);
    // Your view setup code goes here ....

    if(getResources().getBoolean(R.bool.isTablet)) {
        v.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    v.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                } else {
                    v.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                }

                // Can also just use your own preset "max width" value here;
                // This code just lets you fake "wrap_content" value
                getDialog().getWindow().setLayout(viewWithGreatestWidth.getMeasuredWidth(), WindowManager.LayoutParams.WRAP_CONTENT);
            }
        });
    }

    dialog.setContentView(v);
}