BottomSheets
BottomSheet
BottomSheet,我的理解是一种view的呈现样式。如果把相应的view添加下列的属性
采用:
<app:layout_behavior="@string/bottom_sheet_behavior>
即可声明为BottomSheet类型的view,但是其父Layout必须为CoordinatorLayout
。
BottomSheet的五种状态:
BottmSheet在展开,隐藏,折叠的情况下,会设置为不同的状态:
-
STATE_COLLAPSED
默认的折叠状态, bottom sheets只在底部显示一部分布局。显示高度可以通过
app:behavior_peekHeight
或者在代码中获取BottomSheetBehavior
实例设置,默认为0 -
STATE_DRAGGING
过渡状态,此时用户正在向上或者向下拖动bottom sheet
-
STATE_SETTLING
视图从脱离手指自由滑动到最终停下的这一小段时间
-
STATE_EXPANDED
bottom sheet 处于完全展开的状态:当bottom sheet的高度低于CoordinatorLayout容器时,整个bottom sheet都可见;或者CoordinatorLayout容器已经被bottom sheet填满。
-
STATE_HIDDEN
默认无此状态(可通过app:behavior_hideable 启用此状态),启用后用户将能通过向下滑动完全隐藏 bottom sheet。
BottomSheetDialog
BottomSheetDialogd是用BottomSheet的方式封装的Dialog, 它可以让上层View不用必须指定为CoordinatorLayout
。它可以实现类似力扣评论区的效果, 从底部弹出一个Dialog,然后会阻断主窗口,让其呈灰黑色(调用了onPause()
回调), 呈灰黑色也是可以去掉的。
设置BottomSheet的样式
在layout
文件中编写页面,样式例如颜色,圆角在value资源文件中用style来编写,圆角的shape在drawable中定义一个shape文件来编写。
获取view和绑定控件
在代码中,通过inflate
BottomSheetDialog的layout来获取到Dialog的样式,然后按照常规的方法来添加逻辑或者动态修改UI
配合BottomSheetBehavior设置高度
定义一个BottomSheetBehavior, 为了让其和BottomSheetDialog相关联,需要在dialog设置了contentview之后构造,以让它获取一个父布局.
dialog.setContentView(view);
BottomSheetBehavior behavior = BottomSheetBehavior.from((View)view.getParent());
在BottomSheetBehavior的回调中,在改变状态时,通过newState参数判断改变到什么状态,并添加相应的逻辑
behavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { @Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
if(newState==BottomSheetBehavior.STATE_EXPANDED){
ViewGroup.LayoutParams params = bottomSheet.getLayoutParams();
params.height = behavior.getPeekHeight();
bottomSheet.setLayoutParams(params);
}
//下列函数在滑动的时候回调,会修改slideOffset;
// 从peekHight往下,slideOffset取[-1,0]; 往上到maxHight, 取[0,1]
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
);
以上就是设置view的最大高度的方法,demo把最大高度设置为了和peekhight相同的高度,这样可以把BottomSheetDialog设置为固定高度。上面的ViewGroup
可以简单理解为这个view所处的layout,我理解为是它的父布局,所以调整父布局的高度就调整了整体的高度,在代码中,修改的LayoutParams
来实现这个目的。
但在开发中,采用上述的方法会有一个问题:由于默认的弹起状态是STATE_COLLAPSED
, 即使设置了固定高度,在第一次弹出时,仍然可以拉起到一个很高的高度,然后再切换到STATE_EXPANDED
状态,高度为我们预设的高度,这和我们看到主流软件做出来的效果有差异。
解决方法如下:
// 先将状态预置为STATE_EXPANDED,然后再弹出Dialog。弹起之后就是固定的,也没有滑动冲突。
ViewGroup.LayoutParams params = view.getLayoutParams();
params.height = behavior.getPeekHeight();
view.setLayoutParams(params);
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
dialog.show();
去除灰黑色背景效果
抖音评论区也是用的BottomSheetDialog,但是抖音评论区在弹起后背景不会变为灰黑色。
设置代码如下,设置在dialog.show()
之前
if(dialog.getWindow()!=null){
WindowManager.LayoutParams wParams = dialog.getWindow().getAttributes();
wParams.dimAmount = 0.0f; // 完全不暗,背景可见
dialog.getWindow().setAttributes(wParams);
}
WindowManager用于管理Window,它是显示View的最底层,通过view可以获取到它。WindowManager.LayoutParams 继承于ViewGroup.LayoutParams,用于设置Window的参数