前言
以前總以為這個底部彈出的視圖是在普通的視圖中添加的,所以沒太在意它的原理,后來粗略看了一下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