Android支持BottomSheetBehavior不能动态?
Android Support BottomSheetBehavior can't be dynamic?
我正在使用 Android 支持库中的底部 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 中添加所有子视图,那么一切正常。当我尝试以编程方式动态添加视图时,它只是不起作用。
有人遇到过类似的问题吗?
尝试post可运行以查看消息队列:
bottomSheet.post(new Runnable() {
@Override
public void run() {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
或者使用 retrolambda:
bottomSheet.post(() -> bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED));
BottomSheetBehavior 上的动态内容在执行扩展尺寸计算时出现问题。 BottomSheetBehavior 在 onLayoutChild 方法中计算扩展尺寸。但是,当您更改 sheet 的内容时,布局过程会异步启动。即使您调用 RequestLayout 或类似的东西。所以调用的结果是这样的:
- BottomSheetBehavior 有旧的扩展尺寸(在你的情况下我认为它是零)
- 您将内容添加到 BottomSheet。展开的尺寸还是旧的。
- 您将 SetState 调用为 EXPANDED。 BottomSheetBehavior 仍会记住旧的扩展尺寸并启动该尺寸的动画。状态更改为 STATE_SETTLING!
- onLayoutChild 被调用,BottomSheetBehavior 计算新的扩展尺寸。但是动画已经在进行中并且状态是 STATE_SETTLING 所以 BottomSheetBehavior 不会改变它的大小
- 动画完成。 BottomSheet 的大小是旧的。状态更改为 EXPANDED,但 BottomSheetBehavior "forgot" 在动画期间更改了展开大小。
肯定是BottomSheetBehaviour实现的bug。
在我的项目中,我找到了这样的解决方法:
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 的内容。如果状态未展开,只需将其更改为已展开,等到动画完成后再更改内容。
我正在使用 Android 支持库中的底部 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 中添加所有子视图,那么一切正常。当我尝试以编程方式动态添加视图时,它只是不起作用。
有人遇到过类似的问题吗?
尝试post可运行以查看消息队列:
bottomSheet.post(new Runnable() {
@Override
public void run() {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
});
或者使用 retrolambda:
bottomSheet.post(() -> bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED));
BottomSheetBehavior 上的动态内容在执行扩展尺寸计算时出现问题。 BottomSheetBehavior 在 onLayoutChild 方法中计算扩展尺寸。但是,当您更改 sheet 的内容时,布局过程会异步启动。即使您调用 RequestLayout 或类似的东西。所以调用的结果是这样的:
- BottomSheetBehavior 有旧的扩展尺寸(在你的情况下我认为它是零)
- 您将内容添加到 BottomSheet。展开的尺寸还是旧的。
- 您将 SetState 调用为 EXPANDED。 BottomSheetBehavior 仍会记住旧的扩展尺寸并启动该尺寸的动画。状态更改为 STATE_SETTLING!
- onLayoutChild 被调用,BottomSheetBehavior 计算新的扩展尺寸。但是动画已经在进行中并且状态是 STATE_SETTLING 所以 BottomSheetBehavior 不会改变它的大小
- 动画完成。 BottomSheet 的大小是旧的。状态更改为 EXPANDED,但 BottomSheetBehavior "forgot" 在动画期间更改了展开大小。
肯定是BottomSheetBehaviour实现的bug。
在我的项目中,我找到了这样的解决方法:
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 的内容。如果状态未展开,只需将其更改为已展开,等到动画完成后再更改内容。