BottomSheetDialogFragment 在横向模式下不显示全高
Posted
技术标签:
【中文标题】BottomSheetDialogFragment 在横向模式下不显示全高【英文标题】:BottomSheetDialogFragment doesn't show full height in landscape mode 【发布时间】:2018-01-18 17:39:50 【问题描述】:我在我的活动中使用 BottomSheetDialogFragment,对话框在纵向模式下显示全高,但在我切换到横向模式时不显示。
MainActivity.java
public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CustomBottomSheetDialog customBottomSheetDialog = new CustomBottomSheetDialog();
customBottomSheetDialog.show(getSupportFragmentManager(),customBottomSheetDialog.getTag());
CustomBottomSheetDialog
public class CustomBottomSheetDialog extends BottomSheetDialogFragment
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
return View.inflate(getContext(), R.layout.view_config, null);
CustomBottomSheetDialog 布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_
android:background="#fdf107"
android:layout_>
<TextView
android:layout_
android:layout_
android:gravity="center"
android:textColor="@color/colorAccent"
android:text="BottomSheetDialogFragment"/>
</LinearLayout>
在横向模式下,我必须拖动 BottomSheetDialogFragment 才能看到全部内容。
【问题讨论】:
原来这是预期的行为 (issuetracker.google.com/issues/37083487)。引用“Material Design 指南说,底页应该在底页上方区域为 19:6 的高度窥视。由于您的横向屏幕小于 16:9,因此它会窥视规范中的最小高度。 " @Bracadabra 我没有看到你所指的报价。 @clever_trevor 评论好像被删除了。 【参考方案1】:这个问题的解决办法是。
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
super.onViewCreated(view, savedInstanceState);
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
@Override
public void onGlobalLayout()
if (Build.VERSION.SDK_INT < 16)
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
else
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
BottomSheetDialog dialog = (BottomSheetDialog) getDialog();
FrameLayout bottomSheet = (FrameLayout)
dialog.findViewById(android.support.design.R.id.design_bottom_sheet);
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
behavior.setPeekHeight(0); // Remove this line to hide a dark background if you manually hide the dialog.
);
【讨论】:
一旦事件被触发,别忘了注销监听器。 谢谢!我有这个问题:当对话框隐藏时,停电并没有消失。注释掉这一行对我有帮助:behavior.setPeekHeight(0);
哈克,但它有效。这是有风险的,因为它取决于android.support.design.R.id.design_bottom_sheet
,Google 可以随时决定重命名它并导致代码损坏。还有其他方法可以通过原生 Android SDK 方法实现吗?
@Ivan 如果他们在支持库中重命名代码,您的代码将无法编译。
如果你使用androidx
库,你应该使用com.google.android.material.R.id.design_bottom_sheet
【参考方案2】:
这对我有用,是最干净的方法:
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog
val dialog = BottomSheetDialog(requireContext(), theme)
dialog.behavior.state = BottomSheetBehavior.STATE_EXPANDED
return dialog
【讨论】:
如果你也发布一些解释会更有帮助,例如你为什么选择这种方法。请阅读***.com/help/how-to-answer 在最近的api中dialog.behavior没有暴露,是私有的 它是公开的。刚刚检查了一下:dialog.behavior.state 也可以将第二行替换为val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
。
如果您在尝试关闭或隐藏对话框时处于折叠状态,请同时添加:dialog.behavior.skipCollapsed = true
【参考方案3】:
感谢@avez raj 和Prevent dismissal of BottomSheetDialogFragment on touch outside 我写在onCreateDialog()
。
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog
val dialog = super.onCreateDialog(savedInstanceState)
dialog.setOnShowListener
val bottomSheet = dialog.findViewById<View>(
com.google.android.material.R.id.design_bottom_sheet) as? FrameLayout
val behavior = BottomSheetBehavior.from(bottomSheet)
behavior.state = BottomSheetBehavior.STATE_EXPANDED
return dialog
目前我使用MakinTosH解决方案,它更短。
【讨论】:
为什么会这样呢?在什么情况下会变成这样?有官方的处理方式吗?也许我们应该在它没有扩展时以不同的方式处理它?或者它是一个错误?我在 Play 商店也注意到了一个与之相关的奇怪错误:issuetracker.google.com/issues/133809189 @androiddeveloper,好问题,我不知道。 BSDF 是非常错误的观点。尤其是涉及到键盘的时候。感谢您的研究。 但即使没有键盘,它也被折叠成更小的尺寸 @androiddeveloper,我想,谷歌公司的他们每天都在制作奇怪的伙伴组件。程序员必须为每个错误创建解决方法。我的前同事也注意到 BSDF 在全屏键盘上的问题,甚至想用片段而不是 BSDF 重写。 @androiddeveloper,如果他更改代码,我可能会问他详细信息。【参考方案4】:ViewTreeObserver
解决方案对我不起作用,但我找到了一个更好的解决方案 here 并将其转换为 Kotlin。这个没有 ViewTreeObserver
带来的昂贵的计算浪费,并且很好地将功能捆绑到类中。
class ExpandedBottomSheetDialog(context: Context) : BottomSheetDialog(context)
override fun show()
super.show()
// androidx should use: com.google.android.material.R.id.design_bottom_sheet
val view = findViewById<View>(R.id.design_bottom_sheet)
view!!.post
val behavior = BottomSheetBehavior.from(view)
behavior.setState(BottomSheetBehavior.STATE_EXPANDED)
【讨论】:
此解决方案不适用于 BottomSheetDialogFragment
,因为它使用未附加到任何view
的findViewById
(在此阶段为null
)。此外,如果您覆盖show(manager: FragmentManager?, tag: String?)
(请参阅***.com/questions/15729138/…)并使用super.show(manager, tag)
,那么您可能会捕获异常。【参考方案5】:
您可以简单地执行以下操作:
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
super.onViewCreated(view, savedInstanceState)
dialog?.let
val sheet = it as BottomSheetDialog
sheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
// rest of your stuff
【讨论】:
【参考方案6】:这是gestureInsetBottomIgnored
的问题。对于横向,此标志为 false,但对于纵向,此标志为 true。
【讨论】:
【参考方案7】:任何原因添加`onConfigurationChanged后,它不起作用(需要再次横向拖动它)
// support when screen rotate, resize etc.
override fun onConfigurationChanged(newConfig: Configuration)
super.onConfigurationChanged(newConfig)
rvLayoutManager.spanCount = getSpanCount()
rvLayoutManager.requestLayout()
private fun getSpanCount(): Int
val widthPx = resources.displayMetrics.widthPixels
val profileWidth = activity!!.resources.getDimension(R.dimen.profile_width)
return Math.floor((widthPx / profileWidth).toDouble()).toInt()
【讨论】:
以上是关于BottomSheetDialogFragment 在横向模式下不显示全高的主要内容,如果未能解决你的问题,请参考以下文章
如果键盘可见,则防止关闭 BottomSheetDialogFragment
赶上BottomSheetDialogFragment的解雇
Android BottomSheetDialogFragment 闪烁
防止 BottomSheetDialogFragment 覆盖导航栏