Android支持的BottomSheetBehavior无法动态修改?

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中,那么一切都正常工作。但是当我尝试以编程方式动态添加视图时,它就不起作用。

有人遇到过类似的问题吗?


展示你的代码以便更好地理解... - Vickyexpert
1
你能否发布完整的代码,展示如何将视图添加到“BottomSheet”中?因为我刚刚尝试复制,但没有遇到这个问题。 - romtsn
你能否发布一下你正在添加底部表单的外部ViewGroup的代码?如果可能的话,请发布完整的隔离代码以重现此行为。因为正如@rom4ek所说,我也无法重现所述问题。 - Anirudha Agashe
你能展示一下你是如何创建 actionButtonView 的吗? - himanshu1496
遇到了相同的问题。仍然不知道解决方法。 - Volchik
2个回答

3
BottomSheetBehavior存在与其展开大小计算实现相关的动态内容问题。BottomSheetBehavior在onLayoutChild方法中计算展开大小。但是,当您更改底部工作表布局的内容时,该过程会启动异步处理。即使您调用RequestLayout或类似的东西。因此,调用的结果如下:
1. BottomSheetBehavior具有旧的展开大小(在您的情况下,我认为它为零)。 2. 您向BottomSheet添加内容。展开大小仍然是旧的。 3. 您调用SetState以EXPANDED。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();
}

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

解决方法的思路是在BottomSheetBehavior未处于展开状态时永远不更改BottomSheet的内容。如果状态不是展开状态,只需将其更改为展开状态,等待动画完成,然后再更改内容。


1
尝试将可运行对象发布到视图的消息队列中:
bottomSheet.post(new Runnable() {
    @Override
    public void run() {
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    }
});

或者使用Retrolambda:

bottomSheet.post(() -> bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接