Android 自带的bottomsheet满足不了项目中的需求,所以自己写了一个,其实就是一个自定义的RelativeLayout。
主要的功能有:
- 支持同一个界面插入多个弹窗
- 可以设置弹窗的默认高度和某一个弹窗的高度
- 可以设置遮罩效果的透明度跟颜色
- 设置弹窗的弹出时间和插值器
- 点击弹窗遮盖层自动收起弹窗
不足的地方:
- 不能拉住弹窗边缘改变弹窗高度
- 每次设置弹窗时要同时设置高度,否则使用默认高度,而不能自动读取xml布局中的高度
调用方法:
1.首先要在xml布局的根布局中使用CustomBottomSheetLayout
<?xml version="1.0" encoding="utf-8"?>
<com.example.shui.custombottomsheet.CustomBottomSheetLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/bottomSheetLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.shui.custombottomsheet.MainActivity">
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="pushView" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn2"
android:text="pushView2"
android:layout_below ="@+id/btn"
android:layout_centerHorizontal="true"/>
</com.example.shui.custombottomsheet.CustomBottomSheetLayout>
2.获取CustomBottomSheetLayout实例,同时进行默认设置
CustomBottomSheetLayout bsLayout= (CustomBottomSheetLayout) findViewById(R.id.bottomSheetLayout);
bsLayout.setPopBottomSheetCustomHeight(600); //设置弹窗默认高度
bsLayout.setSuperstratumAlpha((float) 0.5); //设置遮盖层透明度
bsLayout.setSuperStratumColor(Color.BLUE); //设置遮盖层颜色
bsLayout.setBottomSheetInterpolator(new AccelerateInterpolator()); //设置弹窗插值器
bsLayout.setShowBottomSheetTime(800); //设置弹窗时间
3.添加弹窗到CustomBottomSheetLayout 中,同时返回来弹窗的view实例,可以使用该view实例进行界面交互
//第一个参数,view的id
//第二个参数,hight为0是默认的弹窗高度高度
//第三个参数,用于记录弹窗时弹出跟flag所匹配的view
View pushView = bsLayout.createBottomSheetLayout(R.layout.bottomsheet1, 0, 0);
Button bsBtn1 = (Button) pushView.findViewById(R.id.bs_btn1);
bsBtn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "pushView", Toast.LENGTH_SHORT).show();
}
});
4.弹出窗口
//参数是弹窗的标志位,在createBottomSheetLayout方法中设置的
bsLayout.popBottomSheet(0);
5.收起窗口
bsLayout.hideBottomSheet();
6.需要支持弹出不同弹窗时,只需要多次调用createBottomSheetLayout(int BottomSheetLayoutId, int hight, int flag)方法就可以了,不过需要注意是该方法的第三个参数需要每次都传入不同的flag作为区分弹窗的标志位,否则报错。最后想显示那个弹窗时调用方法popBottomSheet(int flag)就可以了,参数是之前每个弹窗的标志位。
代码核心
1.生成view同时添加到根布局中且隐藏
/**
* 创建bottomsheet
*
* @param BottomSheetLayoutId view的id
* @param hight 设置弹窗的高度,hight为0是默认的弹窗高度高度
* @param flag view的标记,用于记录弹窗时弹出跟flag所匹配的view
* @return
*/
public View createBottomSheetLayout(int BottomSheetLayoutId, int hight, int flag) {
for (int key:bottomSheetLayoutMap.keySet()){//检查view的flag是否已经被设置,如果被设置抛出异常
if (key==flag)throw new RuntimeException("the BottomSheetLayout flag is in use,so use other flag!");
}
View layout = View.inflate(mContext.getApplicationContext(), BottomSheetLayoutId, null);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, hight == 0 ? popBottomSheetCustomHeight : hight);
lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
layout.setLayoutParams(lp);
layout.setTag(flag);
layout.setVisibility(GONE);//设置view为不可见
layout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//设置空的点击事件,拦截事件,防止点击事件传到遮盖层superstratum;从而点击弹窗空白部分时不会收起弹窗
}
});
bottomSheetLayoutMap.put(flag,layout);//把view添加到map中,当弹窗时弹出key为flag的弹窗
addView(layout);//添加view到当前根布局中
return layout;
}
2.弹出窗口与收起窗口核心是遮盖效果与弹窗动画同时执行
/**
* 弹出bottomsheet
*
* @param flag view的标志位
* @param height bottomsheet内容物的高度 0为view自身高度
* @param time 弹出所需时间 0为默认的时间
* @param value 插值器
*/
public void popBottomSheet(int flag, int height, int time, TimeInterpolator value) {
final View pushView = getBottomSheet(flag);
if (pushView == null) {
Log.e("log","根据flag没有找到view,或者view丢失");
return;
}
if (height != 0) {//高度不等于0时,重新设置弹窗的LayoutParams值,
height = setBSLViewHight(pushView, height);
} else {
height = getViewHeight(pushView);
}
if (height <= 0) {
Log.e("log","弹出高度小于等于0,弹窗失败");
return;
}
AnimatorListenerAdapter adapter = new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
//动画开始时弹窗和遮盖层均可点击和显示
pushView.setVisibility(VISIBLE);
superStratum.setVisibility(VISIBLE);
pushView.setClickable(true);
superStratum.setClickable(true);
}
};
//标志弹出的是哪个窗口,收起窗口时使用
popBottomSheetFlag = flag;
startAnimator(pushView, time, value, adapter, height, 0, 0, superstratumAlpha);
}
/**
* 运行动画
*
* @param pushView 弹出的view
* @param time 动画时间
* @param value 插值器
* @param adapter 动画执行状态监听器
* @param BSStartHight bottomsheet动画开始高度
* @param BSEndHight bottomsheet动画结束高度
* @param SSStartAlpha superStratum动画开始透明度
* @param SSEndAlpha superStratum动画结束透明度
*/
private void startAnimator(View pushView, int time, TimeInterpolator value, AnimatorListenerAdapter adapter, int BSStartHight, int BSEndHight, float SSStartAlpha, float SSEndAlpha) {
ObjectAnimator animator = ObjectAnimator.ofFloat(pushView, "translationY", BSStartHight, BSEndHight);
animator.addListener(adapter);
ObjectAnimator superstratumAnimator = ObjectAnimator.ofFloat(superStratum, "alpha", SSStartAlpha, SSEndAlpha);
AnimatorSet set =new AnimatorSet();
set.setDuration(time == 0 ? showBottomSheetTime : time);
set.setInterpolator(value != null ? value : bottomSheetInterpolator);
set.playTogether(animator,superstratumAnimator);
set.start();
}
/**
* 收起bottomsheet
*
* @param time 动画时间
* @param value 动画的插值器
*/
public void hideBottomSheet(int time, TimeInterpolator value) {
final View pushView = getBottomSheet(popBottomSheetFlag);
popBottomSheetFlag = -1;
if (pushView == null) {
Log.e("log","弹出层丢失,收起bottomsheet失败");
return;
}
RelativeLayout.LayoutParams layoutParams = (LayoutParams) pushView.getLayoutParams();
AnimatorListenerAdapter adapter = new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
//动画开始时设置不能点击
pushView.setClickable(false);
superStratum.setClickable(false);
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
//动画结束时设置为不可见
pushView.setVisibility(GONE);
superStratum.setVisibility(GONE);
}
};
startAnimator(pushView, time, value, adapter, 0, layoutParams.height, superstratumAlpha, 0);
}
下载demo地址为:
http://download.csdn.net/detail/u011959456/9843957