组件介绍
参考资料
源码地址
介绍
底部动作条是ios中常见的界面组件,常用于呈现一组功能给用户.Android在design
兼容包中也引入了这一组件和设计.用户可以自由定制动作条的视图元素和行为.
![此处输入图片的描述][1]
底部动作条的功能上看似和菜单类似,在Android中,在界面上额外弹出功能菜单有四种主要的方式:
ContextMenu
-> 长按操作
OptionMenu
-> 按菜单键
PopuWindow
->目标控件点击
dialog
->对话框
在目前的实际开发中,前两种已经很少用到了,PopuWindow
通常用来显示少量的功能(少于3个),dialog虽然能显示多个功能,但在显示时会打断用户体验,且功能个数也有限制.而且为了保持苹果,安卓的用户体验一致性.会手动设置dialog的位置为下方,以达到iOS中的底部窗口效果.
谷歌引入了底部动作条这一组件作为功能菜单展示的第五种方式,并将其作为材料设计的组成部分之后,就有必要来学习一下它的用法了.
基础布局
首先我们需要在项目中加入design
兼容包的依赖,版本号与SDK中兼容包的版本号保持一致
compile 'com.android.support:design:23.3.0'
之后是在新建项目的actiivty_main.xml
加入底部动作条
其中底部动作条的布局文件为
效果图为
![此处输入图片的描述][2]
[1]: http://aidecn.cn/MD/components-bottomsheet-for-mobile-1b_large_mdpi.png
[2]: https://cms-assets.tutsplus.com/uploads/users/798/posts/26031/image/buttons.png
注意
值得注意的是,如果要在fragment
和activity
的主布局文件中显示(展示效果为不阻挡界面上其他控件的展示和点击事件),则需要布局文件的根元素为CoordinatorLayout
,同时BottomSheetBehavior
所标识的控件一般为可滚动的控件,如NestedScrollView
或RecyclerView
,具备以上两个条件之后,界面就能正常捕获和处理BottomSheet
操作的事件及行为.
用下面的属性标识动作条视图的容器
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
弹出操作
在布局文件中我们可以知道,动作条视图是由BottomSheetBehavior
所标识的,那么在控制动作条的显示的时候,同样也需要得到BottomSheetBehavior
以控制视图的弹出状态.
MainActivity.java
的代码如下
private BottomSheetBehavior mBottomSheetBehavior;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View bottomSheet = findViewById( R.id.bottom_sheet );
Button button1 = (Button) findViewById( R.id.button_1 );
Button button2 = (Button) findViewById( R.id.button_2 );
Button button3 = (Button) findViewById( R.id.button_3 );
button1.setOnClickListener(this);
button2.setOnClickListener(this);
button3.setOnClickListener(this);
mBottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
}
接下来,要展示底部动作条的话,就需要设置BottomSheetBehavior
的状态为STATE_EXPANDED
,与其对应的关闭状态则为STATE_COLLAPSED
,设置点击事件如下
@Override
public void onClick(View v) {
switch( v.getId() ) {
case R.id.button_1: {
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
break;
}
}
}
@Override public void onBackPressed() {
if (mBottomSheetBehavior.getState()==BottomSheetBehavior.STATE_EXPANDED){
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}else {
super.onBackPressed();
}
}
显示控制
我们可以通过设置弹出高度来控制动作条的显示高度
mBottomSheetBehavior.setPeekHeight(300);
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
同时也可以设置BottomSheetBehavior
的回调函数BottomSheetCallback
来动态控制动作条
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
mBottomSheetBehavior.setPeekHeight(0);
}
}
@Override public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
BottomSheetDialogFragment
以上介绍的是非阻塞的底部动作条,它不会影响界面上其他元素的交互.但在iOS的底部动作视图中,是一种阻塞式的模态窗口.类似于对话框.Android中对应的就是BottomSheetDialogFragment
在其setupDialog
方法中我们就可以自由定制动作条的视图及行为了,同时也需要监听动作条的状态以实现在hidden状态下的自动dismiss.
public class MyBottomSheetDialogFragment extends BottomSheetDialogFragment {
private BottomSheetBehavior.BottomSheetCallback callback = new BottomSheetBehavior.BottomSheetCallback() {
@Override public void onStateChanged(@NonNull View bottomSheet, int newState) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss();
}
}
@Override public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
};
@Override public void setupDialog(Dialog dialog, int style) {
super.setupDialog(dialog, style);
View contentView = View.inflate(getContext(),R.layout.dialog_bottom_sheet,null);
dialog.setContentView(contentView);
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) contentView.getParent()).getLayoutParams();
CoordinatorLayout.Behavior behavior = params.getBehavior();
if( behavior != null && behavior instanceof BottomSheetBehavior ) {
((BottomSheetBehavior) behavior).setBottomSheetCallback(callback);
}
}
}
同DialogFragment一样,我们调用show方法来展示它
MyBottomSheetDialogFragment bottomSheetDialogFragment = new MyBottomSheetDialogFragment();
bottomSheetDialogFragment.show(getSupportFragmentManager(), bottomSheetDialogFragment.getTag());