9

我正在使用来自 Android 支持库的 Bottom Sheet,如下所示:

XML:

<LinearLayout
    android:id="@+id/bottomSheetLinearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/fourth_white"
    android:orientation="vertical"
    app:layout_behavior="android.support.design.widget.BottomSheetBehavior" />

我将子视图添加到 LinearLayout:

bottomSheet.addView(actionButtonView);

添加完子视图后,我初始化 BottomSheetBehavior 并展开它:

BottomSheetBehavior sheetBehavior = BottomSheetBehavior.from(bottomSheet);
sheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);

这行不通。什么都没有显示。即使我在 XML 中预设了 LinearLayout 的高度,它也只是全白的。

如果我在 XML 中的 LinearLayout 中添加所有子视图,那么一切正常。当我尝试以编程方式动态添加视图时,它只是不起作用。

有人有类似的问题吗?

4

2 回答 2

3

BottomSheetBehavior 上的动态内容问题与其扩展尺寸计算的实现有关。BottomSheetBehavior 在 onLayoutChild 方法中计算展开后的大小。但是,当您更改工作表布局过程的内容时,会异步启动。即使您调用 RequestLayout 或类似的东西。所以调用的结果是这样的:

  1. BottomSheetBehavior 具有旧的扩展尺寸(在您的情况下,我认为它为零)
  2. 您将内容添加到 BottomSheet。扩展尺寸仍然很旧。
  3. 你调用 SetState 来扩展。BottomSheetBehavior 仍会记住旧的展开尺寸并以该尺寸启动动画。状态更改为 STATE_SETTLING!
  4. onLayoutChild 调用和 BottomSheetBehavior 计算新的扩展大小。但是动画已经在进行中并且状态是 STATE_SETTLING 所以 BottomSheetBehavior 不会改变它的大小
  5. 动画完成。BottomSheet 的大小是旧的。状态更改为 EXPANDED 但 BottomSheetBehavior “忘记”了在动画期间更改了扩展大小。

这肯定是 BottomSheetBehaviour 实现的错误。

在我的项目中,我发现了这样的解决方法:

private void showPanel(final View panelContent) {
    if (panelBehavior.getState()!=BottomSheetBehavior.STATE_EXPANDED) {
        panelBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(final View bottomSheet, int newState) {
                if (newState==BottomSheetBehavior.STATE_EXPANDED) {
                    panelBehavior.setBottomSheetCallback(null);
                    contentView.removeAllViews();
                    contentView.addView(panelContent);
                    panelView.setVisibility(View.VISIBLE);

                }
            }

            @Override
            public void onSlide(View bottomSheet, float slideOffset) {

            }
        });
        panelBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        return;
    }
    contentView.removeAllViews();
    contentView.addView(panelContent);
    panelView.setVisibility(View.VISIBLE);
}

private void hidePanel() {
    panelBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    panelView.setVisibility(View.GONE);
    contentView.removeAllViews();
}

因此,当您需要使用新内容显示 BottomSheet 时,请调用 ShowPanel。当您需要完全隐藏 BottomSheet 时,调用 hidePanel(如果您需要在项目中隐藏它。如果不需要,您可以从方法中删除 setVisibility)。

解决方法的想法是当 BottomSheetBehavior 未处于展开状态时,永远不要更改 BottomSheet 的内容。如果状态没有展开,只需将其更改为展开,等到动画完成后才更改内容。

于 2017-11-19T05:32:26.660 回答
1

尝试将 runnable 发布到查看的消息队列:

bottomSheet.post(new Runnable() {
    @Override
    public void run() {
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    }
});

或者使用retrolambda:

bottomSheet.post(() -> bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED));
于 2016-06-20T12:40:03.067 回答