Java Android BottomSheetDialogFragment 没有完全展开
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37555403/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android BottomSheetDialogFragment does not expand completely
提问by Nandish A
I have the following test bottom sheet implementation.
我有以下测试底部工作表实现。
When I set the peekHeight to a value less than 500, it works. After some value, any increase in peek height will not change how the bottom sheet is expanded. It Just remains there to only drag manually. How do we set the peekHeight programmatically to ensure that the bottom sheet is auto expanded to the peek height.
当我将 peekHeight 设置为小于 500 的值时,它会起作用。在某个值之后,任何窥视高度的增加都不会改变底部工作表的展开方式。它只是留在那里只能手动拖动。我们如何以编程方式设置 peekHeight 以确保底部工作表自动扩展到 peek 高度。
bottom_sheet_dialog_main
bottom_sheet_dialog_main
<?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"
android:id="@+id/locUXCoordinatorLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/locUXView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:orientation="vertical"
app:behavior_hideable="false"
app:behavior_peekHeight="0dp"
app:layout_behavior="@string/bottom_sheet_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="1 Value" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="2 Value" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="3 Value" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="4 Value" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="5 Value" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="6 Value" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="7 Value" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="8 Value" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="9 Value" />
<TextView
android:layout_width="match_parent"
android:layout_height="100dp"
android:text="First Value" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
Java code
Java代码
public class MyBottomSheetDialogFragment extends BottomSheetDialogFragment {
private static BottomSheetBehavior bottomSheetBehavior;
private static View bottomSheetInternal;
private static MyBottomSheetDialogFragment INSTANCE;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
getDialog().setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
CoordinatorLayout coordinatorLayout = (CoordinatorLayout)d.findViewById(R.id.locUXCoordinatorLayout);
bottomSheetInternal = d.findViewById(R.id.locUXView);
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetInternal);
bottomSheetBehavior.setPeekHeight(bottomSheetInternal.getHeight());
bottomSheetInternal.requestLayout();
coordinatorLayout.getLayoutParams().height = bottomSheetInternal.getHeight();
Toast.makeText(getActivity(), "Height is" + bottomSheetInternal.getHeight() + " " + coordinatorLayout.getLayoutParams().height, Toast.LENGTH_LONG).show();
}
});
INSTANCE = this;
return inflater.inflate(R.layout.bottom_sheet_dialog_main, container, false);
}
}
采纳答案by Nandish A
By deeper UI inspection, we find that there is another CoordinatorLayout
that wraps our coordinator layout. The parent CoordinatorLayout
has a FrameLayout
with a BottomSheetBehavior
with the id design_bottom_sheet
. The peek height set from our code above was getting constrained due the match_parent
height of the FrameLayout
with the id design_bottom_sheet
通过更深入的 UI 检查,我们发现还有一个CoordinatorLayout
包装我们的协调器布局。家长CoordinatorLayout
有FrameLayout
一个BottomSheetBehavior
id为design_bottom_sheet
。由于带有 id的match_parent
高度,从我们上面的代码中设置的窥视高度受到限制FrameLayout
design_bottom_sheet
By setting the peek height of the FrameLayout
with the id design_bottom_sheet , this issue was resolved
通过设置FrameLayout
带有 id design_bottom_sheet的 peek height ,这个问题得到解决
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
getDialog().setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
coordinatorLayout = (CoordinatorLayout) d.findViewById(R.id.locUXCoordinatorLayout);
bottomSheetInternal = d.findViewById(R.id.locUXView);
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetInternal);
bottomSheetBehavior.setHidable(false);
BottomSheetBehavior.from((View)coordinatorLayout.getParent()).setPeekHeight(bottomSheetInternal.getHeight());
bottomSheetBehavior.setPeekHeight(bottomSheetInternal.getHeight());
coordinatorLayout.getParent().requestLayout();
}
});
回答by Denshov
I've found another solution. Maybe for future readers it can be useful.
我找到了另一个解决方案。也许对未来的读者来说它可能很有用。
@Override
public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, style);
final View root = View.inflate(getContext(), R.layout.fragment_bottom_sheet_choose_time, null);
dialog.setContentView(root);
initView(root);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) root.getParent()).getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
if (behavior != null && behavior instanceof BottomSheetBehavior) {
mBottomSheetBehavior = (BottomSheetBehavior) behavior;
mBottomSheetBehavior.setBottomSheetCallback(mBottomSheetBehaviorCallback);
root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
root.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int height = root.getMeasuredHeight();
mBottomSheetBehavior.setPeekHeight(height);
}
});
}
}
As @Anthonyeef mentioned, here ViewTreeObserver
is aimed to get the exact measure height after the view is really measured and the GlobalOnLayoutListener
is removed for better performance.
正如@Anthonyeef 所提到的,这里ViewTreeObserver
的目的是在真正测量视图后获得准确的测量高度,并GlobalOnLayoutListener
删除该高度以获得更好的性能。
But please, before using in production, test this solution on different devices and screens, because if your content in bottom sheet is higher than your screen it can produce some strange swipe behavior.
但是,在生产中使用之前,请在不同的设备和屏幕上测试此解决方案,因为如果底部工作表中的内容高于屏幕,它可能会产生一些奇怪的滑动行为。
回答by athysirus
Using this code in onCreateView.
在 onCreateView 中使用此代码。
getDialog().setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) d.findViewById(R.id.design_bottom_sheet);
CoordinatorLayout coordinatorLayout = (CoordinatorLayout) bottomSheet.getParent();
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bottomSheetBehavior.setPeekHeight(bottomSheet.getHeight());
coordinatorLayout.getParent().requestLayout();
}
});
回答by Mike T
Thanks @athysirus for the neat approach. Here is the version I ended up with, in case somebody wants to have a working kotlin sample.
感谢@athysirus 的简洁方法。这是我最终得到的版本,以防有人想要一个可用的 kotlin 样本。
Important to note is, that you should also remove the global layout listener, once done.
需要注意的是,一旦完成,您还应该删除全局布局侦听器。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
val bottomSheet = (dialog as BottomSheetDialog).findViewById<View>(com.google.android.material.R.id.design_bottom_sheet)
BottomSheetBehavior.from<View>(bottomSheet).apply {
state = BottomSheetBehavior.STATE_EXPANDED
peekHeight = 0
}
view.viewTreeObserver.removeOnGlobalLayoutListener(this)
}
})
回答by Paul Spiesberger
Solution in Kotlin inspired by Nandish A's post in more detail. First the layout:
Kotlin 中的解决方案更详细地受Nandish A的帖子启发。首先布局:
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/container_root"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:behavior_hideable="false"
app:behavior_peekHeight="0dp"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<!-- content of the bottom sheet -->
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
And then put this into your BottomSheetDialogFragment
:
然后把它放到你的BottomSheetDialogFragment
:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// ...
dialog.setOnShowListener {
val root = dialog.find<CoordinatorLayout>(R.id.container_root)
val bottomSheetInternal = root.find<ConstraintLayout>(R.id.bottom_sheet)
val bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetInternal)
bottomSheetBehavior.isHideable = false
BottomSheetBehavior.from(root.parent as View).peekHeight = root.height
bottomSheetBehavior.peekHeight = root.height
root.parent.requestLayout()
}
// ...
}
回答by Saba 21
this is how I set peek_height
and layout_height
to bottom sheet view in BottomSheetDialogFragment
这就是我设置peek_height
和layout_height
底部工作表视图的方式BottomSheetDialogFragment
dialog?.setOnShowListener {
val dialog = dialog as BottomSheetDialog
val bottomSheet = dialog.findViewById<FrameLayout>(R.id.design_bottom_sheet)
val coordinatorLayout = bottomSheet?.parent as? CoordinatorLayout
val bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
bottomSheet?.viewTreeObserver?.addOnGlobalLayoutListener {
bottomSheet.viewTreeObserver.removeOnGlobalLayoutListener {}
bottomSheetBehavior.peekHeight = getPopupHeight(.5f)
val params = bottomSheet.layoutParams
params.height = getPopupHeight(1f)
bottomSheet.layoutParams = params
coordinatorLayout?.parent?.requestLayout()
}
}
this method to get percent of screen height
此方法获取屏幕高度的百分比
private fun getPopupHeight(percent: Float): Int {
val displayMetrics = DisplayMetrics()
activity?.windowManager?.defaultDisplay?.getMetrics(displayMetrics)
return (displayMetrics.heightPixels * percent).toInt()
}
回答by Muhammad Umair Shafique
Kotlinsafe way of achieving this is:
Kotlin实现这一目标的安全方法是:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
dialog.setOnShowListener {
val dialog = it as BottomSheetDialog
val bottomSheet = dialog.findViewById<View>(R.id.design_bottom_sheet)
bottomSheet?.let { sheet ->
dialog.behavior.peekHeight = sheet.height
sheet.parent.parent.requestLayout()
}
}
}
NOTE:No need to wrap your layout in coordinator layout.
注意:无需将您的布局包装在协调器布局中。
Works like charm.
像魅力一样工作。
回答by seinta
This made the trick for me! My class extends the BottomSheetDialogFragment
这对我来说是个窍门!我的课程扩展了BottomSheetDialogFragment
@Override
public void onStart()
{
super.onStart();
Dialog dialog = getDialog();
if (dialog != null)
{
View bottomSheet = dialog.findViewById(R.id.bottom_sheet);
bottomSheet.getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
}
View view = getView();
view.post(() -> {
View bottomSheet = dialog.findViewById(R.id.bottom_sheet);
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());
((View) bottomSheet.getParent()).setBackgroundColor(Color.TRANSPARENT);
});
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.screen_delivery_type, container, false);
getDialog().setOnShowListener(new DialogInterface.OnShowListener()
{
@Override
public void onShow(DialogInterface dialog)
{
BottomSheetDialog d = (BottomSheetDialog) dialog;
FrameLayout bottomSheet = (FrameLayout) d.findViewById(R.id.bottom_sheet);
CoordinatorLayout coordinatorLayout = (CoordinatorLayout) bottomSheet.getParent();
BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bottomSheetBehavior.setPeekHeight(bottomSheet.getHeight());
bottomSheetBehavior.setFitToContents(true);
bottomSheetBehavior.setExpandedOffset(0);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
coordinatorLayout.getParent().requestLayout();
}
});
}