我的BottomSheetView
有animateLayoutChanges="true"
。最初它显示很好。但是,如果将视图的visibility
(BottomSheetView
内)从GONE
更改为VISIBLE
,该应用会混乱计算,而我的BottomSheetView
会移到顶部屏幕。我尝试在layout_gravity=bottom
布局的根目录设置BottomSheetView
。但没有成功。
在更改任何视图的可见性之前,我有BottomSheetView
的图像。 (点击图片查看完整尺寸)
在我更改视图(GONE
到VISIBLE
或VISIBLE
到GONE
)的可见性后,我的BottomSheetView会移到顶部。 (点击图片查看完整尺寸)
我想,在计算视图width
和height
的衡量标准时,Android正在搞乱。有什么方法可以解决这个问题吗?
我还试图让我的BottomSheetView完全扩展以匹配父视图,但不知何故,这使得height
的{{1}}长于电话屏幕和插件创建滚动问题。
预期解决方案:
1>即使更改了视图的BottomSheetView
,也可以防止BottomSheetView
更改其位置。
OR
2>使visibility
匹配父级,以便在弄乱计算后看起来不会很糟糕。
答案 0 :(得分:7)
我遇到了同样的问题,并决定找到一个解决方案。我能够找到根本原因,但遗憾的是我目前没有看到很好的修复。
原因:
底部表格行为和LayoutTransition之间出现问题。创建LayoutTransition时,它会在视图上创建一个OnLayoutChangeListener,以便它可以捕获其endValues并使用正确的值设置动画师。首次调用onLayout()
时,底部表单行为的parent.onLayout(child)
调用会触发此OnLayoutChangeListener。父级将像往常一样布局子级,忽略行为稍后会改变的任何偏移。问题出在这里。此时视图的值由OnLayoutChangeListener捕获并存储在动画制作器中。动画运行时,它将为这些值设置动画,而不是您的行为定义的位置。不幸的是,LayoutTransition类不允许我们访问动画师以允许更新结束值。
修复:
目前,我没有看到涉及LayoutTransitions的优雅修复。我将提交一个访问和更新LayoutTransition动画师的方法的bug。现在,您可以使用layoutTransition.setAnimateParentHierachy(false)
禁用父容器上的任何layoutTransition。然后,您可以自己动画更改。我会尽快用一个有效的例子来更新我的答案。
答案 1 :(得分:7)
BottomSheetBehavior暂时不能与LayoutTransition
(animateLayoutChanges="true"
)一起使用。我会努力修复。
目前,您可以使用Transition
代替。这样的东西会使内部视图褪色,并使底部纸张的大小生动。
ViewGroup bottomSheet = ...;
View hidingView = ...;
TransitionManager.beginDelayedTransition(bottomSheet);
hidingView.setVisibility(View.GONE);
您可以参考Applying a Transition了解更多信息,包括如何自定义动画。
答案 2 :(得分:1)
在BottomSheetDialog默认布局(design_bottom_sheet_dialog)中,对话框的design_bottom_sheet
FrameLayout上的重力为 TOP :
android:layout_gravity="center_horizontal|top"
我真的不知道为什么底部 SheetDialog的重力位于顶部。
您需要在项目中创建相同的布局文件(内容和名称相同),并将此行替换为:
android:layout_gravity="center_horizontal|bottom"
答案 3 :(得分:1)
这个问题是两年多以前提出的,但不幸的是,问题仍然存在。
我终于有了一个解决方案,可以在拥有addView
的同时将对removeView
和animateLayoutChanges="true"
函数的调用保留在BottomSheet中。
BottomSheetBehavior
更改后无法计算正确的高度,因此高度必须保持不变。为此,我将BottomSheet
的高度设置为match_parent
并将其分为两个子级:内容和一个Space
,该内容根据内容的高度而改变高度。>
要最好地模仿BottomSheet
的真实行为,还需要添加一个TouchToDismiss视图,该视图在扩展BottomSheet
时使背景变暗,而在扩展BottomSheet
时也要关闭<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/show_bottom_sheet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show bottom sheet"/>
<View
android:id="@+id/touch_to_dismiss"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:background="#9000"/>
<LinearLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<Space
android:id="@+id/space"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<LinearLayout
android:id="@+id/bottom_sheet_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:animateLayoutChanges="true">
<Button
android:id="@+id/add_or_remove_another_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add another view"/>
<TextView
android:id="@+id/another_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Another view"/>
</LinearLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
用户在内容之外按。
代码如下:
activity.xml
BottomSheetBehavior bottomSheetBehavior;
View touchToDismiss;
LinearLayout bottomSheet;
Button showBottomSheet;
Space space;
LinearLayout bottomSheetContent;
Button addOrRemoveAnotherView;
TextView anotherView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
touchToDismiss = findViewById(R.id.touch_to_dismiss);
touchToDismiss.setVisibility(View.GONE);
touchToDismiss.setOnClickListener(this);
bottomSheet = findViewById(R.id.bottom_sheet);
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
bottomSheetBehavior.setPeekHeight(0);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN || newState == BottomSheetBehavior.STATE_COLLAPSED) {
touchToDismiss.setVisibility(View.GONE);
}else {
touchToDismiss.setVisibility(View.VISIBLE);
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
touchToDismiss.setAlpha(getRealOffset());
}
});
showBottomSheet = findViewById(R.id.show_bottom_sheet);
showBottomSheet.setOnClickListener(this);
space = findViewById(R.id.space);
bottomSheetContent = findViewById(R.id.bottom_sheet_content);
addOrRemoveAnotherView = findViewById(R.id.add_or_remove_another_view);
addOrRemoveAnotherView.setOnClickListener(this);
anotherView = findViewById(R.id.another_view);
bottomSheetContent.removeView(anotherView);
}
@Override
public void onClick(View v) {
if (v == showBottomSheet)
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
else if (v == addOrRemoveAnotherView) {
if (anotherView.getParent() == null)
bottomSheetContent.addView(anotherView);
else
bottomSheetContent.removeView(anotherView);
}
else if (v == touchToDismiss)
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
/**
* Since the height does not change and remains at match_parent, it is required to calculate the true offset.
* @return Real offset of the BottomSheet content.
*/
public float getRealOffset() {
float num = (space.getHeight() + bottomSheetContent.getHeight()) - (bottomSheet.getY() + space.getHeight());
float den = bottomSheetContent.getHeight();
return (num / den);
}
activity.java
{{1}}
希望这对某人有用,因为问题仍然存在!
答案 4 :(得分:0)
如果您的视图允许,请将可见性设置为 INVISIBLE 而不是 GONE。
答案 5 :(得分:0)
在我们的例子中,我们在按钮组件上显示了一个进度条。这是隐藏按钮文本并显示进度条。这导致底部片断的跳跃。使用 Invisible 而不是 Gone 解决了这个问题。