如何更改 BottomSheetDialog 的默认高度?
How do I change the default height of a BottomSheetDialog?
我一直在使用 Support Library 23.2 中添加的新 BottomSheetDialog,但我想更改对话框的默认高度。我知道它可能与控制初始高度的 behavior_peekHeight
属性有关,但是当我无法直接访问 BottomSheetBehavior
时如何在 BottomSheetDialog
中设置它?
您可以在 Activity 中设置 bottomSheetDialogTheme
,覆盖 bottomSheetStyle
属性的 behavior_peekHeight
:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="bottomSheetDialogTheme">@style/AppBottomSheetDialogTheme</item>
</style>
<style name="AppBottomSheetDialogTheme"
parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">@style/AppModalStyle</item>
</style>
<style name="AppModalStyle"
parent="Widget.Design.BottomSheet.Modal">
<item name="behavior_peekHeight">@dimen/custom_peek_height</item>
</style>
同样的技术也可以用于其他属性,例如将 <item name="behavior_hideable">true</item>
添加到 AppModalStyle
以更改底部 sheet 是否可隐藏。
另一种方法是继承 BottomSheetDialogFragment
并控制设置内容视图的方式和时间。向上查看视图树,您可以获得 BottomSheetDialog
包装内容视图的行为。这不是很好的解决方案,因为它需要更多的布局通道。重要的是,当底部 sheet 的状态为 STATE_HIDDEN
时,我们必须关闭对话框,否则我们显然违反了库中提供的实现。
以编程方式设置 peek 高度后,内容视图必须调用 requestLayout()
,这确实是另一个布局过程。
public class CustomBottomSheetDialogFragment extends BottomSheetDialogFragment {
private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
setStateText(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(getContext(), R.layout.bottom_sheet_dialog_content_view, null);
dialog.setContentView(contentView);
mBottomSheetBehavior = BottomSheetBehavior.from(((View) contentView.getParent()));
if (mBottomSheetBehavior != null) {
mBottomSheetBehavior.setBottomSheetCallback(mBottomSheetBehaviorCallback);
mBottomSheetBehavior.setPeekHeight(peekHeight);
contentView.requestLayout();
}
}
styles.xml
<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">@style/bottomSheetStyleWrapper</item>
</style>
<style name="bottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal">
<item name="behavior_peekHeight">500dp</item>
</style>
BottomSheetDialog dialog = new BottomSheetDialog(this, R.style.BottomSheetDialog);
dialog.setContentView(R.layout.layout_bottom_sheet);
dialog.show();
您可以在代码中使用BottomSheetBehavior
BottomSheetDialog dialog = new BottomSheetDialog(content);
.
.
.
dialog.setContentView(view);
BottomSheetBehavior mBehavior = BottomSheetBehavior.from((View) view.getParent());
mBehavior.setPeekHeight(your dialog height)
dialog.show();
结合 Nick 和 litao 的解决方案,这是我们所做的完整版本:
BottomSheetDialog bottomSheet = new BottomSheetDialog(context);
View view = View.inflate(context, R.layout.your_action_sheet, null);
bottomSheet.setContentView(view);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(((View) view.getParent()));
bottomSheetBehavior.setPeekHeight(1000);
bottomSheet.show();
我得到了一个 hack 并使用了它。
如果你想以编程方式进行。
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View view, int i) {
behavior.setPeekHeight(yourMinHeight);
}
@Override
public void onSlide(@NonNull View view, float v) {
}
});
谢谢。
我是这样决定这个问题的:
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = BottomSheetDialog(context)
val view = View.inflate(context, R.layout.bottom_dialog, null)
val heightInPixels = 500
val params = ViewGroup.LayoutParams(MATCH_PARENT, heightInPixels)
dialog.setContentView(view, params)
return dialog
}
主要部分是方法 setContentView(view, params)
,您可以在其中设置对话框的视图和设置所需高度的布局参数。
适合我
override fun onStart() {
super.onStart()
dialog?.also {
val bottomSheet = dialog.findViewById<View>(R.id.design_bottom_sheet)
bottomSheet.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
val behavior = BottomSheetBehavior.from<View>(bottomSheet)
behavior.peekHeight = resources.displayMetrics.heightPixels //replace to whatever you want
view?.requestLayout()
}
}
老实说,我不知道为什么还没有人提到这些简单的方法:
override fun onResume() {
super.onResume()
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
// or since com.google.android.material:material:1.1.0-beta01
(dialog as? BottomSheetDialog)?.behavior?.state = BottomSheetBehavior.STATE_EXPANDED
}
//or
dialog.behavior.peekheight = YOUR_VALUE
直接回答问题
Q: How can I directly access the BottomSheetBehavior height?
A: dialog.behavior.peekheight
我们想要实现这一点的真正方法是实际使 LayoutParams 起作用。当扩充对话框的内容视图时,不在对话框 Window
中传递 parentView
将使 rootView 的 xml 配置实际上不起作用。
所以这是一个解决方案:
val contentWidth = ViewGroup.LayoutParams.MATCH_PARENT
val contentHeight = 500 // px
dialog.setContentView(view, ViewGroup.LayoutParams(contentWidth, contentHeight))
您可以使用 BottomSheetDialogFragment
并以编程方式进行。
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
(dialog as? BottomSheetDialog)?.let {
it.behavior.peekHeight = PEEK_HEIGHT
}
return inflater.inflate(R.layout.bottom_sheet_dialog_fragement, container, false)
}
如果您使用的是 BottomSheetDialogFragment,请复制并粘贴此代码
private View bottomSheet;
@Override public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
}
View view = getView();
view.post(() -> {
View parent = (View) view.getParent();
CoordinatorLayout.LayoutParams params =
(CoordinatorLayout.LayoutParams) (parent).getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) behavior;
bottomSheetBehavior.setPeekHeight(view.getMeasuredHeight());
// Here you can play with the height of the bottom sheet like pass height as- [view.getMeasuredHeight()/2]
((View) bottomSheet.getParent()).setBackgroundColor(Color.TRANSPARENT);
});
}
}
使用此代码设置 DialogFragment 或 BottomSheetDialogFragment 的高度。对话框将根据不同的屏幕高度调整其高度
override fun onStart() {
super.onStart()
val window = dialog?.window
val ratio = 1.0
if (window != null && activity != null) {
val heightDialog = (getScreenHeight(requireActivity()) * 0.9f).toInt()
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, (heightDialog * ratio).toInt())
window.setGravity(Gravity.BOTTOM)
}
}
您可以在 onStart()
方法中从 getBehaviour()
检索 BottomSheetBehavior
对象,然后从那里修改 peek 高度。
@Override
protected void onStart() {
super.onStart();
getBehavior().setPeekHeight(/* Peek Height in px */);
}
我可以全屏显示 BottomSheetDialog(STATE_EXPANDED)。我在我的 Activity 中使用它。
private void showBottomSheetDialog() {
View dialogView = LayoutInflater.from(this).inflate(R.layout.your_custom_layout, null);
BottomSheetDialog dialog = new BottomSheetDialog(NewWorkoutPlanActivity.this);
dialog.setContentView(dialogView);
FrameLayout bottomSheet = (FrameLayout) dialog.findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams();
int windowHeight = getWindowHeight();
if (layoutParams != null) {
layoutParams.height = windowHeight;
}
bottomSheet.setLayoutParams(layoutParams);
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
dialog.show();
}
private int getWindowHeight() {
// Calculate window height for fullscreen use
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.heightPixels;
}
如果您正在扩展 BottomSheetDialogFragment,您可以执行以下操作来获取 BottomSheetBehavior:
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
//Must add any view here, actual view will be inflated in onCreateView
dialog.setContentView(new View(getContext()));
//Dialog wraps view in frame layout
View root = dialog.findViewById(R.id.design_bottom_sheet);
//Now we have access to BottomSheetBehavior
BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(root);
//Do whatever you need:
behavior.setPeekHeight(320, true);
behavior.setState(BottomSheetBehavior.STATE_HALF_EXPANDED);
return dialog;
}
然后照常重写 onCreateView:
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//inflate your bottom sheet layout:
View root = inflater.inflate(R.layout.browser_bottom_sheet, container, false);
//Do what you need with views:
ViewPager viewPager = root.findViewById(R.id.viewpager);
...........
return root;
}
我的底部 sheet 对话框有回收视图,没有要显示的项目,所以它正在缩小,但假设你想将 peek 高度设置为 85%,而不管 Recyclerview 中是否存在项目,试试这个解决方案。
在扩展 BottomSheetDialogFragment
的 class 中添加以下代码
override fun onStart() {
super.onStart()
(dialog as BottomSheetDialog).behavior.peekHeight = getBottomSheetDialogDefaultHeight()
dialog?.let {
val bottomSheet = it.findViewById<View>(R.id.design_bottom_sheet)
bottomSheet.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
}
}
private fun getBottomSheetDialogDefaultHeight(): Int {
val displayMetrics = DisplayMetrics()
(context as Activity?)?.windowManager?.defaultDisplay?.getMetrics(displayMetrics)
return displayMetrics.heightPixels * 85 / 100
}
我一直在使用 Support Library 23.2 中添加的新 BottomSheetDialog,但我想更改对话框的默认高度。我知道它可能与控制初始高度的 behavior_peekHeight
属性有关,但是当我无法直接访问 BottomSheetBehavior
时如何在 BottomSheetDialog
中设置它?
您可以在 Activity 中设置 bottomSheetDialogTheme
,覆盖 bottomSheetStyle
属性的 behavior_peekHeight
:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="bottomSheetDialogTheme">@style/AppBottomSheetDialogTheme</item>
</style>
<style name="AppBottomSheetDialogTheme"
parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">@style/AppModalStyle</item>
</style>
<style name="AppModalStyle"
parent="Widget.Design.BottomSheet.Modal">
<item name="behavior_peekHeight">@dimen/custom_peek_height</item>
</style>
同样的技术也可以用于其他属性,例如将 <item name="behavior_hideable">true</item>
添加到 AppModalStyle
以更改底部 sheet 是否可隐藏。
另一种方法是继承 BottomSheetDialogFragment
并控制设置内容视图的方式和时间。向上查看视图树,您可以获得 BottomSheetDialog
包装内容视图的行为。这不是很好的解决方案,因为它需要更多的布局通道。重要的是,当底部 sheet 的状态为 STATE_HIDDEN
时,我们必须关闭对话框,否则我们显然违反了库中提供的实现。
以编程方式设置 peek 高度后,内容视图必须调用 requestLayout()
,这确实是另一个布局过程。
public class CustomBottomSheetDialogFragment extends BottomSheetDialogFragment {
private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
setStateText(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(getContext(), R.layout.bottom_sheet_dialog_content_view, null);
dialog.setContentView(contentView);
mBottomSheetBehavior = BottomSheetBehavior.from(((View) contentView.getParent()));
if (mBottomSheetBehavior != null) {
mBottomSheetBehavior.setBottomSheetCallback(mBottomSheetBehaviorCallback);
mBottomSheetBehavior.setPeekHeight(peekHeight);
contentView.requestLayout();
}
}
styles.xml
<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">@style/bottomSheetStyleWrapper</item>
</style>
<style name="bottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal">
<item name="behavior_peekHeight">500dp</item>
</style>
BottomSheetDialog dialog = new BottomSheetDialog(this, R.style.BottomSheetDialog);
dialog.setContentView(R.layout.layout_bottom_sheet);
dialog.show();
您可以在代码中使用BottomSheetBehavior
BottomSheetDialog dialog = new BottomSheetDialog(content);
.
.
.
dialog.setContentView(view);
BottomSheetBehavior mBehavior = BottomSheetBehavior.from((View) view.getParent());
mBehavior.setPeekHeight(your dialog height)
dialog.show();
结合 Nick 和 litao 的解决方案,这是我们所做的完整版本:
BottomSheetDialog bottomSheet = new BottomSheetDialog(context);
View view = View.inflate(context, R.layout.your_action_sheet, null);
bottomSheet.setContentView(view);
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(((View) view.getParent()));
bottomSheetBehavior.setPeekHeight(1000);
bottomSheet.show();
我得到了一个 hack 并使用了它。
如果你想以编程方式进行。
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View view, int i) {
behavior.setPeekHeight(yourMinHeight);
}
@Override
public void onSlide(@NonNull View view, float v) {
}
});
谢谢。
我是这样决定这个问题的:
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = BottomSheetDialog(context)
val view = View.inflate(context, R.layout.bottom_dialog, null)
val heightInPixels = 500
val params = ViewGroup.LayoutParams(MATCH_PARENT, heightInPixels)
dialog.setContentView(view, params)
return dialog
}
主要部分是方法 setContentView(view, params)
,您可以在其中设置对话框的视图和设置所需高度的布局参数。
适合我
override fun onStart() {
super.onStart()
dialog?.also {
val bottomSheet = dialog.findViewById<View>(R.id.design_bottom_sheet)
bottomSheet.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
val behavior = BottomSheetBehavior.from<View>(bottomSheet)
behavior.peekHeight = resources.displayMetrics.heightPixels //replace to whatever you want
view?.requestLayout()
}
}
老实说,我不知道为什么还没有人提到这些简单的方法:
override fun onResume() {
super.onResume()
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
// or since com.google.android.material:material:1.1.0-beta01
(dialog as? BottomSheetDialog)?.behavior?.state = BottomSheetBehavior.STATE_EXPANDED
}
//or
dialog.behavior.peekheight = YOUR_VALUE
直接回答问题
Q: How can I directly access the BottomSheetBehavior height?
A:
dialog.behavior.peekheight
我们想要实现这一点的真正方法是实际使 LayoutParams 起作用。当扩充对话框的内容视图时,不在对话框 Window
中传递 parentView
将使 rootView 的 xml 配置实际上不起作用。
所以这是一个解决方案:
val contentWidth = ViewGroup.LayoutParams.MATCH_PARENT
val contentHeight = 500 // px
dialog.setContentView(view, ViewGroup.LayoutParams(contentWidth, contentHeight))
您可以使用 BottomSheetDialogFragment
并以编程方式进行。
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
(dialog as? BottomSheetDialog)?.let {
it.behavior.peekHeight = PEEK_HEIGHT
}
return inflater.inflate(R.layout.bottom_sheet_dialog_fragement, container, false)
}
如果您使用的是 BottomSheetDialogFragment,请复制并粘贴此代码
private View bottomSheet;
@Override public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
bottomSheet = dialog.findViewById(R.id.design_bottom_sheet);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
}
View view = getView();
view.post(() -> {
View parent = (View) view.getParent();
CoordinatorLayout.LayoutParams params =
(CoordinatorLayout.LayoutParams) (parent).getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
BottomSheetBehavior bottomSheetBehavior = (BottomSheetBehavior) behavior;
bottomSheetBehavior.setPeekHeight(view.getMeasuredHeight());
// Here you can play with the height of the bottom sheet like pass height as- [view.getMeasuredHeight()/2]
((View) bottomSheet.getParent()).setBackgroundColor(Color.TRANSPARENT);
});
}
}
使用此代码设置 DialogFragment 或 BottomSheetDialogFragment 的高度。对话框将根据不同的屏幕高度调整其高度
override fun onStart() {
super.onStart()
val window = dialog?.window
val ratio = 1.0
if (window != null && activity != null) {
val heightDialog = (getScreenHeight(requireActivity()) * 0.9f).toInt()
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, (heightDialog * ratio).toInt())
window.setGravity(Gravity.BOTTOM)
}
}
您可以在 onStart()
方法中从 getBehaviour()
检索 BottomSheetBehavior
对象,然后从那里修改 peek 高度。
@Override
protected void onStart() {
super.onStart();
getBehavior().setPeekHeight(/* Peek Height in px */);
}
我可以全屏显示 BottomSheetDialog(STATE_EXPANDED)。我在我的 Activity 中使用它。
private void showBottomSheetDialog() {
View dialogView = LayoutInflater.from(this).inflate(R.layout.your_custom_layout, null);
BottomSheetDialog dialog = new BottomSheetDialog(NewWorkoutPlanActivity.this);
dialog.setContentView(dialogView);
FrameLayout bottomSheet = (FrameLayout) dialog.findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams();
int windowHeight = getWindowHeight();
if (layoutParams != null) {
layoutParams.height = windowHeight;
}
bottomSheet.setLayoutParams(layoutParams);
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
dialog.show();
}
private int getWindowHeight() {
// Calculate window height for fullscreen use
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.heightPixels;
}
如果您正在扩展 BottomSheetDialogFragment,您可以执行以下操作来获取 BottomSheetBehavior:
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
//Must add any view here, actual view will be inflated in onCreateView
dialog.setContentView(new View(getContext()));
//Dialog wraps view in frame layout
View root = dialog.findViewById(R.id.design_bottom_sheet);
//Now we have access to BottomSheetBehavior
BottomSheetBehavior<View> behavior = BottomSheetBehavior.from(root);
//Do whatever you need:
behavior.setPeekHeight(320, true);
behavior.setState(BottomSheetBehavior.STATE_HALF_EXPANDED);
return dialog;
}
然后照常重写 onCreateView:
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//inflate your bottom sheet layout:
View root = inflater.inflate(R.layout.browser_bottom_sheet, container, false);
//Do what you need with views:
ViewPager viewPager = root.findViewById(R.id.viewpager);
...........
return root;
}
我的底部 sheet 对话框有回收视图,没有要显示的项目,所以它正在缩小,但假设你想将 peek 高度设置为 85%,而不管 Recyclerview 中是否存在项目,试试这个解决方案。
在扩展 BottomSheetDialogFragment
的 class 中添加以下代码override fun onStart() {
super.onStart()
(dialog as BottomSheetDialog).behavior.peekHeight = getBottomSheetDialogDefaultHeight()
dialog?.let {
val bottomSheet = it.findViewById<View>(R.id.design_bottom_sheet)
bottomSheet.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
}
}
private fun getBottomSheetDialogDefaultHeight(): Int {
val displayMetrics = DisplayMetrics()
(context as Activity?)?.windowManager?.defaultDisplay?.getMetrics(displayMetrics)
return displayMetrics.heightPixels * 85 / 100
}