背景
关于Google在Metrail Design 风格中新推出的dialog,BottomSheetDialog 在现在不少App中都能看到,我就在抖音和网易新闻上看到过,不管是样式还是新颖的交互来说都是不错的,国内设计师习惯将弹窗的最底部增加一个功能性的按键
现状
类似于上面图片这种,弹窗的高度还要根据数据条目的个数去适配,如果使用普通的dialog 即没有好的交互体验,弹出的高度也需要我们自己计算,这无疑是增加了开发难度;
找方案
使用BottomSheetDialog ,底部去支付的按钮始终是在数据的下方,如果只有两三条数据还好,如果数据过多则需要将列表滑动到最下方才能看到功能键,这无疑是一个非常糟糕的交互,今天我们就通过查看BottomSheetDialog 来修改他,让他可以存放一个始终放下最下方的区域,先来看一下他的源码
public class BottomSheetDialog extends AppCompatDialog {
....省略部分代码
@Override
public void setContentView(@LayoutRes int layoutResId) {
super.setContentView(wrapInBottomSheet(layoutResId, null, null));
}
/**
* 我们知道要实现BottomSheetDialog 离不开BottomSheetBehavior 的支持,
*这里将 contentView 添加到 一个拥有 BottomSheetBehavior 的布局当中
**/
private View wrapInBottomSheet(int layoutResId, View view, ViewGroup.LayoutParams params) {
final CoordinatorLayout coordinator = (CoordinatorLayout) View.inflate(getContext(),
R.layout.design_bottom_sheet_dialog, null);//事先加载一个拥有BottomSheetBehavior 的布局
if (layoutResId != 0 && view == null) {
view = getLayoutInflater().inflate(layoutResId, coordinator, false);
}
FrameLayout bottomSheet = (FrameLayout) coordinator.findViewById(R.id.design_bottom_sheet);
mBehavior = BottomSheetBehavior.from(bottomSheet);//获取到布局BottomSheetBehavior
mBehavior.setBottomSheetCallback(mBottomSheetCallback);
mBehavior.setHideable(mCancelable);
if (params == null) {
bottomSheet.addView(view);//将contentView 添加入容器中
} else {
bottomSheet.addView(view, params);//将contentView 添加入容器中
}
// We treat the CoordinatorLayout as outside the dialog though it is technically inside
coordinator.findViewById(R.id.touch_outside).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mCancelable && isShowing() && shouldWindowCloseOnTouchOutside()) {
cancel();
}
}
});
return coordinator;
}
....省略部分代码
}
复制代码
其实从上面这段代码根本看不出来什么,只是知道contentView被放入的一个拥有BottomSheetBehavior 的容器总,想要在原有的基础上增加一个可拓展的底部功能区域,就需要修改原始的layout布局,
design_bottom_sheet_dialog.xml 布局文件
<FrameLayout
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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<View
android:id="@+id/touch_outside"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:importantForAccessibility="no"
android:soundEffectsEnabled="false"
tools:ignore="UnusedAttribute"/>
<FrameLayout
android:id="@+id/design_bottom_sheet"
style="?attr/bottomSheetStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
app:layout_behavior="@string/bottom_sheet_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</FrameLayout>
复制代码
CoordinatorLayout 包裹了我们的contentView的容器,也就是design_bottom_sheet 这个FrameLayout,想要给底部增加一个按钮,只需要让CoordinatorLayout 的marginBottom 与 底部的区域高度相等即可,
修改后的文件如下:
<FrameLayout
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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<View
android:id="@+id/touch_outside"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:importantForAccessibility="no"
android:soundEffectsEnabled="false"
tools:ignore="UnusedAttribute"/>
<FrameLayout
android:id="@+id/design_bottom_sheet"
style="?attr/bottomSheetStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
app:layout_behavior="@string/bottom_sheet_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<FrameLayout
android:id="@+id/bottom_design_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"/>
</FrameLayout>
复制代码
修改后的BottomSheetDialog 如下
open class BaseBottomSheetDialog : AppCompatDialog {
private var mBehavior: TsmBottomSheetBehavior<FrameLayout>? = null
private var mCancelable = true
private var mCanceledOnTouchOutside = true
private var mCanceledOnTouchOutsideSet = false
protected var mContext: Activity? = null
constructor(context: Activity) : this(context, 0) {
this.mContext = context
}
constructor(context: Context, @StyleRes theme: Int) : super(
context,
getThemeResId(context, theme)
) {
// We hide the title bar for any style configuration. Otherwise, there will be a gap
// above the bottom sheet when it is expanded.
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
}
protected constructor(
context: Context, cancelable: Boolean,
cancelListener: DialogInterface.OnCancelListener?
) : super(context, cancelable, cancelListener) {
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
mCancelable = cancelable
}
override fun setContentView(@LayoutRes layoutResId: Int) {
super.setContentView(wrapInBottomSheet(layoutResId, 0, null, null))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window!!.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT
)
}
override fun setContentView(view: View) {
super.setContentView(wrapInBottomSheet(0, 0, view, null))
}
override fun setContentView(view: View, params: ViewGroup.LayoutParams?) {
super.setContentView(wrapInBottomSheet(0, 0, view, params))
}
fun setContentView(view: View?, @LayoutRes bottom: Int) {
super.setContentView(wrapInBottomSheet(0, bottom, view, null))
}
override fun setCancelable(cancelable: Boolean) {
super.setCancelable(cancelable)
if (mCancelable != cancelable) {
mCancelable = cancelable
if (mBehavior != null) {
mBehavior!!.isHideable = cancelable
}
}
}
override fun setCanceledOnTouchOutside(cancel: Boolean) {
super.setCanceledOnTouchOutside(cancel)
if (cancel && !mCancelable) {
mCancelable = true
}
mCanceledOnTouchOutside = cancel
mCanceledOnTouchOutsideSet = true
}
private fun wrapInBottomSheet(
layoutResId: Int,
bottomLayoutId: Int,
view: View?,
params: ViewGroup.LayoutParams?
): View {
var view = view
val parent = View.inflate(context, R.layout.zr_bottom_sheet_dialog_with_bottom, null)
val coordinator = parent.findViewById<View>(R.id.coordinator) as CoordinatorLayout
if (layoutResId != 0 && view == null) {
view = layoutInflater.inflate(layoutResId, coordinator, false)
}
if (bottomLayoutId != 0) {
val bottomView = layoutInflater.inflate(bottomLayoutId, coordinator, false)
val fl = parent.findViewById<FrameLayout>(R.id.bottom_design_bottom_sheet)
fl.addView(bottomView)
coordinator.viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener {
override fun onGlobalLayout() {
coordinator.viewTreeObserver.removeOnGlobalLayoutListener(this)
val p2 = coordinator.layoutParams as FrameLayout.LayoutParams
p2.setMargins(0, dp2px(context, 60f), 0, bottomView.height)
coordinator.layoutParams = p2
val p1 = fl.layoutParams
p1.height = bottomView.height
fl.layoutParams = p1
}
})
// bottomView.isClickable=true
}
val bottomSheet = coordinator.findViewById<View>(R.id.design_bottom_sheet) as FrameLayout
bottomSheet.setOnClickListener { }
mBehavior = TsmBottomSheetBehavior.from(bottomSheet)
mBehavior?.setBottomSheetCallback(mBottomSheetCallback)
mBehavior?.setHideable(mCancelable)
if (params == null) {
bottomSheet.addView(view)
} else {
bottomSheet.addView(view, params)
}
// We treat the CoordinatorLayout as outside the dialog though it is technically inside
coordinator.findViewById<View>(R.id.touch_outside).setOnClickListener {
if (mCancelable && isShowing && shouldWindowCloseOnTouchOutside()) {
cancel()
}
}
parent?.findViewById<View>(R.id.container)?.setOnClickListener {
if (mCancelable && isShowing && shouldWindowCloseOnTouchOutside()) {
cancel()
}
}
return parent
}
private fun shouldWindowCloseOnTouchOutside(): Boolean {
if (!mCanceledOnTouchOutsideSet) {
if (Build.VERSION.SDK_INT < 11) {
mCanceledOnTouchOutside = true
} else {
val a =
context.obtainStyledAttributes(intArrayOf(android.R.attr.windowCloseOnTouchOutside))
mCanceledOnTouchOutside = a.getBoolean(0, true)
a.recycle()
}
mCanceledOnTouchOutsideSet = true
}
return mCanceledOnTouchOutside
}
private val mBottomSheetCallback: TsmBottomSheetBehavior.TsmBottomSheetCallback = object : TsmBottomSheetBehavior.TsmBottomSheetCallback() {
override fun onStateChanged(
bottomSheet: View,
@BottomSheetBehavior.State newState: Int
) {
// if (newState == BottomSheetBehavior.STATE_HIDDEN) {
// dismiss();
// }
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
}
companion object {
private fun getThemeResId(context: Context, themeId: Int): Int {
var themeId = themeId
if (themeId == 0) {
// If the provided theme is 0, then retrieve the dialogTheme from our theme
val outValue = TypedValue()
themeId = if (context.theme.resolveAttribute(
R.attr.bottomSheetDialogTheme, outValue, true
)
) {
outValue.resourceId
} else {
// bottomSheetDialogTheme is not provided; we default to our light theme
R.style.Theme_Design_Light_BottomSheetDialog
}
}
return themeId
}
}
open fun dp2px(context: Context, dp: Float): Int {
val scale: Float = context.getResources().getDisplayMetrics().density
return (dp * scale + 0.5f).toInt()
}
}
复制代码
此时写完之后的效果是
底部的高度是通过布局计算的,不需要指定高度,但是需要单独传递一个底部固定部分的id,然后动态添加进去
此时修改过后的BottomSheetDialog 还有一些粗陋,再次封装一下即可使用
abstract class TsmBaseBottomSheetDialog : BaseBottomSheetDialog {
constructor(context: Activity) :super(context, R.style.bottom_sheet_dilog){
initDialog()
}
open fun initDialog() {
//需要设置这个才能设置状态栏和导航栏颜色
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
window?.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
//设置状态栏颜色
window?.setStatusBarColor(Color.TRANSPARENT)
}
//回复默认导航栏颜色
val view = LayoutInflater.from(context).inflate(layoutId, null)
setContentView(view, bottomLayoutId)
behaver = TsmBottomSheetBehavior.from(view.parent as View)
behaver?.setBottomSheetCallback(object : TsmBottomSheetBehavior.TsmBottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss()
}
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
})
}
/**
* 可以控制菜单状态
*/
protected var behaver: TsmBottomSheetBehavior<View>?=null
override fun show() {
initViews()
super.show()
}
protected abstract val layoutId: Int
protected open val bottomLayoutId: Int
protected get() = 0
protected abstract fun initViews()
}
复制代码
再次封装后使用则会方便很多
封装后使用如下
class TsmBottomSheetDialog(context: Activity) : TsmBaseBottomSheetDialog(context) {
override val layoutId: Int
protected get() = R.layout.dialog_tsm_bottom_sheet
override fun initViews() {
val recycler_view = findViewById<RecyclerView>(R.id.recycler_view)
recycler_view!!.adapter = object :BaseQuickAdapter<String,BaseViewHolder>(R.layout.item_simple_test,getList(23)){
override fun convert(holder: BaseViewHolder, item: String) {
holder?.setText(R.id.tv_item, item)
}
}
}
private fun getList(count: Int): MutableList<String>? {
var list: MutableList<String> = MutableList(count,init = {
it.toString()
})
return list
}
override val bottomLayoutId: Int
protected get() = R.layout.botttom_sheet_bottom_view
}
复制代码
但是在使用过程中产品对于现阶段的BottomSheetDialog 的表现形式并不是非常满意
问题
先来说一下我们的问题都有哪些:
- 由于给BottomSheetDialog 添加了一个顶部的margin,导致在BottomSheetDialog 完全展开时,点击顶部透明区域时,dialog并不会收缩
- 产品在看了原生BottomSheetDialog 的展示形式时,感觉类似抖音之类的展示形式比较好,也就是整个BottomSheetDialog 除了展开就是隐藏,不想要中间的那个折叠状态,我们上下最终的效果图
1.点击外部不能消失的问题
先来修改第一个问题,想要解决外部不能点击的问题很简单,我们只需要让最外层的View 可以点击就好了,
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2015 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<FrameLayout
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:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:clickable="true">///// 这里增加可以点击,同时在dialog中添加点击事件即可
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<View
android:id="@+id/touch_outside"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:importantForAccessibility="no"
android:soundEffectsEnabled="false"
tools:ignore="UnusedAttribute"/>
<FrameLayout
android:id="@+id/design_bottom_sheet"
style="?attr/bottomSheetStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
app:layout_behavior="com.tsm.tsmmodelapp.behavior.TsmBottomSheetBehavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<FrameLayout
android:id="@+id/bottom_design_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:clickable="true" ///这里的作用是屏蔽底部View 的点击事件,不让他传递到下一层
android:background="#ffffff">
</FrameLayout>
</FrameLayout>
复制代码
2.折叠问题
第二个问题就比较严重了,由于 BottomSheetDialog 很多信息我们在外界都获取不到,想要实现上述所说的问题就必须要重写BottomSheetBehavior , 并修改他的代码,我们这里就先看看我们需要改什么吧,
public boolean onLayoutChild(@NonNull CoordinatorLayout parent, @NonNull V child, int layoutDirection) {
... 省略部分代码
if (state == STATE_EXPANDED) {
ViewCompat.offsetTopAndBottom(child, getExpandedOffset());
} else if (state == STATE_HALF_EXPANDED) {
ViewCompat.offsetTopAndBottom(child, halfExpandedOffset);
} else if (hideable && state == STATE_HIDDEN) {
ViewCompat.offsetTopAndBottom(child, parentHeight);
} else if (state == STATE_COLLAPSED) {
ViewCompat.offsetTopAndBottom(child, collapsedOffset);
} else if (state == STATE_DRAGGING || state == STATE_SETTLING) {
ViewCompat.offsetTopAndBottom(child, savedTop - child.getTop());
}
...省略部分代码
}
复制代码
onLayoutChild 这个方法是在布局完成后调用,可以看到在布局完成后他是根据不同的状态来确定展示形式,而我们的需求比较粗暴,无非就是全部展开或者消失,这里就直接变成
public boolean onLayoutChild(@NonNull CoordinatorLayout parent, @NonNull V child, int layoutDirection) {
... 省略部分代码
ViewCompat.offsetTopAndBottom(child, getExpandedOffset());
...省略部分代码
}
复制代码
全部都是完全展开的形式,
这里处理完就剩下一个拖动事件了,由于他是使用了NestScroll 等一系列的事件分发的方式,我们只需要关注最后一帧的滑动事件就好了,所以这里需要看一下onStopNestedScroll 这个方法
public void onStopNestedScroll(
@NonNull CoordinatorLayout coordinatorLayout,
@NonNull V child,
@NonNull View target,
int type) {
if (child.getTop() == getExpandedOffset()) {///如果是展开,那么状态就是3
setStateInternal(STATE_EXPANDED);
return;
}
if (nestedScrollingChildRef == null
|| target != nestedScrollingChildRef.get()
|| !nestedScrolled)
return;
}
int top;
int targetState;
if (lastNestedScrollDy > 0) {
if (fitToContents) {
top = fitToContentsOffset;
targetState = STATE_EXPANDED;
} else {
int currentTop = child.getTop();
if (currentTop > halfExpandedOffset) {
top = halfExpandedOffset;
targetState = STATE_HALF_EXPANDED;
} else {
top = expandedOffset;
targetState = STATE_EXPANDED;
}
}
} else if (hideable && shouldHide(child, getYVelocity())) {
top = parentHeight;
targetState = STATE_HIDDEN;
} else if (lastNestedScrollDy == 0) {
int currentTop = child.getTop();
if (fitToContents) {
if (Math.abs(currentTop - fitToContentsOffset) < Math.abs(currentTop - collapsedOffset)) {
top = fitToContentsOffset;
targetState = STATE_EXPANDED;
} else {
top = collapsedOffset;
targetState = STATE_COLLAPSED;
}
} else {
if (currentTop < halfExpandedOffset) {
if (currentTop < Math.abs(currentTop - collapsedOffset)) {
top = expandedOffset;
targetState = STATE_EXPANDED;
} else {
top = halfExpandedOffset;
targetState = STATE_HALF_EXPANDED;
}
} else {
if (Math.abs(currentTop - halfExpandedOffset) < Math.abs(currentTop - collapsedOffset)) {
top = halfExpandedOffset;
targetState = STATE_HALF_EXPANDED;
} else {
top = collapsedOffset;
targetState = STATE_COLLAPSED;
}
}
}
} else {
if (fitToContents) {
top = collapsedOffset;
targetState = STATE_COLLAPSED;
} else {
// Settle to nearest height.
int currentTop = child.getTop();
if (Math.abs(currentTop - halfExpandedOffset) < Math.abs(currentTop - collapsedOffset)) {
top = halfExpandedOffset;
targetState = STATE_HALF_EXPANDED;
} else {
top = collapsedOffset;
targetState = STATE_COLLAPSED;
}
}
}
startSettlingAnimation(child, targetState, top, false);
nestedScrolled = false;
}
复制代码
其实这里很多属性我也不是很了解,但是我能看一下大概,具体修改后的代码如下,
public void onStopNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull V child, @NonNull View target, int type) {
if (child.getTop() == this.getExpandedOffset()) {
this.setStateInternal(3);
} else if (this.nestedScrollingChildRef != null && target == this.nestedScrollingChildRef.get() && this.nestedScrolled) {
int top;
byte targetState;
if (this.lastNestedScrollDy > 0) {
top = this.getExpandedOffset();
targetState = 3;
} else if (this.hideable && this.shouldHide(child, this.getYVelocity())) {
top = this.parentHeight;
targetState = 5;
} else {
int currentTop;
if (this.lastNestedScrollDy == 0) {//最后一帧没有滑动
currentTop = child.getTop();
if (currentTop < this.halfExpandedOffset){ //小于折叠高度 那么就收缩
targetState = STATE_HIDDEN;
top = this.parentHeight;
}else{//其他展开
top = this.getExpandedOffset();
targetState = 3;
}
}else {
currentTop = child.getTop();
///大于折叠高度,并小于最大高度展开
if (Math.abs(currentTop - this.halfExpandedOffset) < Math.abs(currentTop - this.collapsedOffset)) {
top = this.getExpandedOffset();
targetState = 3;
} else {
top = this.parentHeight;///收起
targetState = 5;
}
}
}
this.startSettlingAnimation(child, targetState, top, false);
this.nestedScrolled = false;
}
}
复制代码
去除了很多中间的状态的代码,反而看起来更简单了, 这里是嵌套滑动的整改,如果没有嵌套滑动,则调用的是onViewReleased 这个方法,所以对这个方法我们也要修改
public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
int top;
byte targetState;
int currentTop;
if (yvel < 0.0F) {
if (TsmBottomSheetBehavior.this.fitToContents) {
top = TsmBottomSheetBehavior.this.fitToContentsOffset;
targetState = STATE_EXPANDED;
} else {
currentTop = releasedChild.getTop();
if (currentTop > TsmBottomSheetBehavior.this.halfExpandedOffset) {
top = TsmBottomSheetBehavior.this.halfExpandedOffset;
targetState = STATE_EXPANDED;
} else {
top = TsmBottomSheetBehavior.this.expandedOffset;
targetState = STATE_EXPANDED;
}
}
} else if (TsmBottomSheetBehavior.this.hideable && TsmBottomSheetBehavior.this.shouldHide(releasedChild, yvel) && (releasedChild.getTop() > TsmBottomSheetBehavior.this.collapsedOffset || Math.abs(xvel) < Math.abs(yvel))) {
top = TsmBottomSheetBehavior.this.parentHeight;
targetState = STATE_HIDDEN;
} else if (yvel != 0.0F && Math.abs(xvel) <= Math.abs(yvel)) {
if (TsmBottomSheetBehavior.this.fitToContents) {
top = TsmBottomSheetBehavior.this.parentHeight;
targetState = STATE_HIDDEN;
} else {
currentTop = releasedChild.getTop();
if (Math.abs(currentTop - TsmBottomSheetBehavior.this.halfExpandedOffset) < Math.abs(currentTop - TsmBottomSheetBehavior.this.collapsedOffset)) {
top = TsmBottomSheetBehavior.this.expandedOffset;
targetState = STATE_EXPANDED;
} else {
top = TsmBottomSheetBehavior.this.parentHeight;
targetState = STATE_HIDDEN;
}
}
} else {
currentTop = releasedChild.getTop();
if (TsmBottomSheetBehavior.this.fitToContents) {
if (Math.abs(currentTop - TsmBottomSheetBehavior.this.fitToContentsOffset) < Math.abs(currentTop - TsmBottomSheetBehavior.this.collapsedOffset)) {
top = TsmBottomSheetBehavior.this.fitToContentsOffset;
targetState = STATE_EXPANDED;
} else {
top = TsmBottomSheetBehavior.this.parentHeight;
targetState = STATE_HIDDEN;
}
} else if (currentTop < TsmBottomSheetBehavior.this.halfExpandedOffset) {
if (currentTop < Math.abs(currentTop - TsmBottomSheetBehavior.this.collapsedOffset)) {
top = TsmBottomSheetBehavior.this.expandedOffset;
targetState = STATE_EXPANDED;
} else {
top = TsmBottomSheetBehavior.this.parentHeight;
targetState = STATE_HIDDEN;
}
} else if (Math.abs(currentTop - TsmBottomSheetBehavior.this.halfExpandedOffset) < Math.abs(currentTop - TsmBottomSheetBehavior.this.collapsedOffset)) {
top = TsmBottomSheetBehavior.this.parentHeight;
targetState = STATE_HIDDEN;
} else {
top = TsmBottomSheetBehavior.this.parentHeight;
targetState = STATE_HIDDEN;
}
}
TsmBottomSheetBehavior.this.startSettlingAnimation(releasedChild, targetState, top, true);
}
}
复制代码
到了这里就结束了
由于修改这个代码比较多,所以还是分享一个github 的地址吧,这样方便大家使用github去看看>>
本文作者:大前端研发中心-田守明