问题
我正在使用
BottomSheetDialogFragment
作为我的模态底页,并想设置最大宽度,以便在平板电脑/大屏幕上 BottomSheet
不会占据屏幕的整个宽度。我该如何解决这个问题?谢谢!
相关代码&资源
fragment_bottomsheet.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/BottomSheetStyle">
<GridLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alignmentMode="alignBounds"
android:columnOrderPreserved="false"
android:columnCount="3"
android:paddingTop="16dp"
android:paddingBottom="8dp"
android:paddingRight="8dp"
android:paddingLeft="8dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/image1"
android:text="Open"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/image2"
android:text="Save"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/image3"
android:text="Send"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/image4"
android:text="Upload"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/image5"
android:text="Share"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableTop="@drawable/iamge6"
android:text="More"/>
</GridLayout>
</android.support.design.widget.CoordinatorLayout>
res/values/styles.xml:
<style name="BottomSheetStyle">
<item name="android:layout_height">match_parent</item>
<item name="android:layout_width">match_parent</item>
<item name="android:layout_gravity">center_horizontal</item>
</style>
res/values-w600dp/styles.xml:
<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);
}
本质上,这允许我根据显示为我的
BottomSheet
动态指定尺寸。
考虑到设备的像素密度和方向的 OP 答案的变体:
public final class MyBottomSheetDialogFragment extends BottomSheetDialogFragment {
...
private static int dpToPx(int dp) {
// https://developer.android.com/guide/practices/screens_support.html#dips-pels
float density = Resources.getSystem().getDisplayMetrics().density;
return (int) ((dp * density) + 0.5f);
}
@Override
public void onResume() {
super.onResume();
Configuration configuration = getActivity().getResources().getConfiguration();
if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE &&
configuration.screenWidthDp > 450) {
// you can go more fancy and vary the bottom sheet width depending on the screen width
// see recommendations on https://material.io/components/sheets-bottom#specs
getDialog().getWindow().setLayout(ViewUtils.dpToPx(450), -1);
}
}
}
正如您所提到的,BottomSheetDialogFragment 似乎不尊重“wrap_content”(它始终在宽度上与父级匹配,即使它包含的所有视图的宽度都为“wrap_content”)。我发现对我来说最好的解决方法是利用 OnGlobalLayoutListener 来监听适当的时间来调整宽度。例子:
@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);
}
如果想纯xml做,可以设置一个样式,用
android:maxWidth
例如:
<LinearLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@color/white"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
style="@style/styleWithFixedWidth"
>
在
styles.xml
<style name="styleWithFixedWidth">
<item name="android:maxWidth">550dp</item>
</style>
这对我有用
BottomSheetDialogFragment
。我可以用这个设置最大宽度:
dialog.maxWidth = Resources.getSystem().displayMetrics.widthPixels
您可以在
onCreateDialog
功能中进行设置。此示例将底部工作表的宽度设置为显示的宽度。
希望这有帮助!