前言
以前总以为这个底部弹出的视图是在普通的视图中添加的,所以没太在意它的原理,后来粗略看了一下AlertDialog源码发现它是Dialog的子类,将View添加到WindowManager产生的Window对象中显示在屏幕图层的最上层。看了一下网上别人写的源码,感觉代码挺简单的,不过用起来不方便,于是封装了一下。给大伙看一下效果。
演示一演示二
项目地址
https://github.com/Ccapton/BottomDialog
关键源码解析:
我是用AlertDialog的Builder设计模式封装这个BottomDialog的,也方便大家熟悉这个控件。下面是关键的Builder类代码
public static class Builder{
private LinearLayout bottomLayout; // 根布局
private View contentView; // 内容布局
private Dialog dialog; // dialog对象
private boolean hasAnimation = true; // 是否开启位移动画的标志位
private Context context; // activity或fragment的上下文对象
private int layoutId; // 内容布局文件id
public Builder(Context context) {
this.context = context;
// 从指定的布局文件中初始化根布局(不限于LinearLayout)
bottomLayout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.layout_bottomdialog,null);
}
public Builder setContentView(int layoutId){
this.layoutId = layoutId;
// 设置内容布局,使其绑定到父布局bottomLayout,使其宽高属性生效
this.contentView = LayoutInflater.from(context).inflate(this.layoutId,bottomLayout);
return Builder.this;
}
public Builder setContentView(View contentView){
this.contentView = contentView;
// 这个方法的弊端是contentView根布局宽高属性没有生效
this.bottomLayout.addView(contentView);
return Builder.this;
}
public Builder setHasAnimation(boolean hasAnimation){
this.hasAnimation = hasAnimation;
return Builder.this;
}
public BottomDialog create(){
BottomDialog bottomDialog = new BottomDialog(); // 初始化bottomDialog对象
dialog = new Dialog(context,R.style.BottomDialog); // 初始化dialog对象
contentView.measure(0, 0); // 测量contentView
bottomLayout.measure(0,0); // 测量bottomLayout
// 为Dialog添加View
dialog.setContentView(bottomLayout);
Window dialogWindow = dialog.getWindow(); // 从dialog对象中获取window对象
// 设置Gravity,使contentView的初始位置在Window最底部,如果不设置则默认在屏幕的中央,就达不到在屏幕底部显示的效果了
dialogWindow.setGravity(Gravity.BOTTOM);
if(hasAnimation)
dialogWindow.setWindowAnimations(R.style.DialogAnimation);
/*
*设置Window参数
*/
WindowManager.LayoutParams lp = dialogWindow.getAttributes();
lp.x = 0;
lp.y = 0;
lp.width = (int) context.getResources().getDisplayMetrics().widthPixels;
lp.height = bottomLayout.getMeasuredHeight();
Log.i("BottomDialog","width = "+lp.width);
Log.i("BottomDialog","height = "+lp.height);
lp.alpha = 9f; // 透明度
dialogWindow.setAttributes(lp);
// 显示dialog
dialog.show();
bottomDialog.dialog = this.dialog;
bottomDialog.contentView = this.contentView;
return bottomDialog;
}
}
这个封装控件大致就是这样,有兴趣了解的朋友请来我的github看看
https://github.com/Ccapton/BottomDialog
https://github.com/Ccapton
网友评论