三行代码
废话不在前面说,直接上代码!
- 将 XML 根布局设置为 CoordinatorLayout
<android.support.design.widget.CoordinatorLayout
- 将要要弹出的三段式抽屉根布局设置 layout_behavior 属性
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
- 将要要弹出的三段式抽屉根布局设置 behavior_fitToContents属性
app:behavior_fitToContents="false"
效果如下图:
这里稍微讲解一下,更多内容看后面:
layout_behavior 属性要配合 CoordinatorLayout 一起使用,behavior_fitToContents 设置为 false 的时候是三段式,默认值为 true,对应两段抽屉。
官方说明
实际上我解释再多,都不如官方说明写的清楚,所以先上官方说明,后面再啰嗦
https://developer.android.google.cn/reference/com/google/android/material/bottomsheet/BottomSheetBehavior?hl=en
仔细讲解
先看详细代码吧!
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.baidu.mapapi.map.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<LinearLayout
android:id="@+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="visible"
app:behavior_hideable="false"
app:behavior_peekHeight="102dp"
app:behavior_fitToContents="false"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
tools:ignore="MissingPrefix">
...
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
实际就是 CoordinatorLayout 内放了一个地图和一个 LinearLayout (抽屉),layout_behavior 要在 CoordinatorLayout 总才生效,BottomSheetBehavior 用的就是官方的,手动打字就能自动导入了,但是要注意下是不是新的,旧的可能没有中间段这个状态。
这里有几个属性要注意下:
app:behavior_hideable="false"
app:behavior_peekHeight="102dp"
app:behavior_fitToContents="false"
app:behavior_halfExpandedRatio="0.5"
-
behavior_hideable
这个属性设置是否可以消失在屏幕最下方
-
behavior_peekHeight
这个是初始显示的高度,也是最小高度
-
behavior_fitToContents
这个是设置是两端还是三段,默认是两端,值为 true
-
behavior_halfExpandedRatio
这个是设置中间段的比例的,默认是 0.5
实际上还可以在代码总监听状态的变化,如下:
holder = findViewById(R.id.bottom_sheet);
BottomSheetBehavior<LinearLayout> behavior = BottomSheetBehavior.from(holder);
behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View view, int newState) {
if (newState == BottomSheetBehavior.STATE_EXPANDED || newState == BottomSheetBehavior.STATE_HALF_EXPANDED ) {
locate.setVisibility(View.GONE);
}else if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
locate.setVisibility(View.VISIBLE);
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
}
});
这里 onStateChanged 函数监听状态改变,onSlide 函数监听滑动的过程。
详细说明
如果还想具体了解 BottomSheetBehavior 的原理的话,可以看下面这篇文章,很详细,我写不来
//BottomSheetBehavior实现高德地图首页效果之原理篇
https://blog.csdn.net/future234/article/details/113481095
探讨过程
之前一直有想法想自定义一套控件实现高德地图那种三段式抽屉的效果,奈何一直干不成事情,一拖再拖,直到后面公司设计师有要求,需要在地图上仿照一个这样的东西,才终于动手了。首先在网上查找了一些资料,发现这样一个三段式的效果都不是用自定义控件实现的,要达到这样的丝滑流畅效果是要点功夫,最后没干劲了直接上了 cv 大法,用别人的,可是效果还是不太行!
终于,昨天想总结一下的时候,看了官方的 BottomSheetBehavior 源码,原来官方已经支持了三段式抽屉,真是走了一大段弯路,不够也收获很大,对 BottomSheetBehavior 有了一定了解。
下面说说网上的一些实现吧,大致有 BottomSheetBehavior 和 MotionLayout 两种,而且大多都是抄来抄去,或者挂羊头卖狗肉,良莠不齐,下面介绍我觉得还可用的两篇博客吧。
-
自定义 BottomSheetBehavior 实现
//Android仿高德地图打车的三段式 BottomSheet
https://blog.csdn.net/qq_33339175/article/details/103025601
实际上这个博主已经实现了三段式抽屉,而且讲解的很清楚,但是我用的时候发现不知道为社么中间状态停不住,停下一段时间后又会扩展到整个屏幕,后面就没用了。
//BottomSheetBehavior 重写
https://www.jianshu.com/p/9cecfabd6118
这个是上面博主的灵感来源,可以使抽屉在任何位置停住,两篇博客都讲的很清楚,看了很有帮助。
-
使用 MotionLayout 实现
//使用MotionLayout实现高德地图 BottomSheet 效果
https://www.wanandroid.com/blog/show/2611
这篇博客是使用 MotionLayout 实现的,可是我嫌他用了 RxJava,不想多引入一个库,读者可自行试试。
结语
官方支持了三段式抽屉用起来很方便,但是不知道的话可能会和我一样走不少弯路吧,希望这篇文章对读者有帮助!
end