工作中,我们免不了需要使用Dialog显示各种各样的提示页面,但是呢,有的需要透明度,有的需要取消黑暗度,或者对显示的位置和大小要求等等,不一而足,于是就产生
了自己封装一个高大上的Dialog来满足工作当中需要的各种各样的需求。
其实呢,封装Dialog,最主要的地方就是在于dialog的Window的封装,通过getWindow获取到Window后,使用它可以对Dialog做一些自定义的内容。下面请看base类的代码:
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import com.creditease.ceinstallment.ui.activity.base.BaseActivity;
import com.creditease.chuangxin.yifenqi.R;
/**
* Created by zgb on 2016/1/5.
*/
public abstract class BaseDialog extends Dialog implements DialogInterface.OnDismissListener {
protected Context context;
protected View localView;
public static int mScreenWidth;
public static int mScreenHeight;
private float alpha = 1.0f;//背景透明度
private float dim = 0.0f;//背景模糊度
private int gravity = Gravity.CENTER;
private boolean isAnimation = false;
private boolean isWidth = false;//widthMargin传入的不是margin,而是真正的宽度值
private int widthMargin = 0;
private int height = WindowManager.LayoutParams.WRAP_CONTENT;
public BaseDialog(Context context) {
super(context);
WindowManager wm = (WindowManager) getContext()
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metric = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metric);
mScreenWidth = metric.widthPixels;
mScreenHeight = metric.heightPixels;
this.context = context;
isAnimation =false;
}
public BaseDialog(Context context, int gravity) {
this(context);
this.gravity = gravity;
}
public BaseDialog(Context context, float alpha, float dim) {
this(context);
this.alpha = alpha;
this.dim = dim;
}
public BaseDialog(Context context, int widthMargin, int height) {
this(context);
this.widthMargin = widthMargin;
this.height = height;
}
public BaseDialog(Context context, int gravity, float alpha, float dim) {
this(context);
this.gravity = gravity;
this.alpha = alpha;
this.dim = dim;
}
public BaseDialog(Context context, int gravity, float alpha, float dim, boolean isAnimation) {
this(context);
this.gravity = gravity;
this.alpha = alpha;
this.dim = dim;
this.isAnimation = isAnimation;
}
public BaseDialog(Context context, int widthMargin, int height, int gravity) {
this(context);
this.widthMargin = widthMargin;
this.height = height;
this.gravity = gravity;
}
public BaseDialog(Context context, int widthMargin, int height, int gravity, boolean isAnimation) {
this(context);
this.widthMargin = widthMargin;
this.height = height;
this.gravity = gravity;
this.isAnimation = isAnimation;
}
public BaseDialog(Context context, int widthMargin, int height, int gravity, float alpha, float dim) {
this(context);
this.widthMargin = widthMargin;
this.height = height;
this.gravity = gravity;
this.alpha = alpha;
this.dim = dim;
}
public BaseDialog(Context context, int widthMargin, int height, int gravity, float alpha, float dim, boolean isAnimation) {
this(context);
this.widthMargin = widthMargin;
this.height = height;
this.gravity = gravity;
this.alpha = alpha;
this.dim = dim;
this.isAnimation = isAnimation;
}
public BaseDialog(Context context, int widthMargin, int gravity, boolean isAnimation) {
this(context);
this.widthMargin = widthMargin;
this.gravity = gravity;
this.isAnimation = isAnimation;
}
public BaseDialog(Context context, int widthMargin, int height, int gravity, float alpha, float dim, boolean isAnimation,boolean isWidth) {
this(context);
this.widthMargin = widthMargin;
this.height = height;
this.gravity = gravity;
this.alpha = alpha;
this.dim = dim;
this.isAnimation = isAnimation;
this.isWidth = isWidth;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 这行代码换掉dialog默认背景,否则dialog的边缘发虚透明而且很宽
// 总之达不到想要的效果
getWindow().setBackgroundDrawableResource(android.R.color.transparent);
LayoutInflater inflater = ((BaseActivity) context).getLayoutInflater();
localView = inflater.inflate(getLayout(), null);
setContentView(localView);
//获取屏幕宽高
WindowManager wm = (WindowManager) getContext()
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metric = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metric);
mScreenWidth = metric.widthPixels;
mScreenHeight = metric.heightPixels;
//设置dialog的大小
if(!isWidth){
getWindow().setLayout(mScreenWidth - widthMargin, height);
}else{
getWindow().setLayout(widthMargin, height);
}
//设置dialog显示位置,居中、底部,顶部等等
getWindow().setGravity(gravity);
WindowManager.LayoutParams lp = getWindow().getAttributes();
//设置dialog透明度
lp.alpha = alpha;
//设置dialog黑暗度,即除了内容之外的区域是否显示的黑暗度,0完全透明,1完全黑暗
lp.dimAmount = dim;
getWindow().setAttributes(lp);
if (isAnimation) {
getWindow().setWindowAnimations(R.style.dialogWindowAnim);
}
initView();
initListener();
setOnDismissListener(this);
setCanceledOnTouchOutside(setOutside());
setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
if(setKeyBack()){
dismiss();
}
}
return false;
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
/**
* 获取到子类的布局
* @return
*/
protected abstract int getLayout();
/**
* 初始化View
*/
protected abstract void initView();
/**
* 监听
*/
protected abstract void initListener();
/**
* 设置点击dialog以外的地方是否可以dismiss
* @return
*/
protected boolean setOutside(){
return true;
}
/**
* 点击硬返回键时dialog以外的地方是否可以dismiss
* @return
*/
protected boolean setKeyBack(){
return true;
}
public void showDialog() {
show();
}
/**
* dialog消失的时候可以做一些处理
* @param dialogInterface
*/
@Override
public void onDismiss(DialogInterface dialogInterface) {
}
}
代码中的注释写的还算可以,这里就做过多的解释了,唯一的不足的地方就是需要各种各样的构造方法去满足传入不同的参数,因为在new出dialog之前将参数实例化,否则onCreate方法不一定拿得到正确的参数值,会导致崩溃,我觉得这可能跟dialog的初始化流程有关,需要再仔细研究一下源码,或者为每个参数写一个protected的方法设置参数也是可以的。
下面是一个loading的dialog的具体实现,代码如下:
/**
* Created by zgb on 2016/1/5.
*/
public class LoadingProgressDialog extends BaseDialog {
private TextView titleView;
private String title;
private boolean isCanBack = true;
private boolean isOutSide = true;
public LoadingProgressDialog(Context context) {
super(context, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, Gravity.CENTER, 0.7f, 0.0f, false, true);
this.context = context;
}
public LoadingProgressDialog(Context context, String title) {
this(context);
this.title = title;
}
public LoadingProgressDialog(Context context, String title, boolean isOutSide, boolean isCanBack) {
this(context, title);
this.isOutSide = isOutSide;
this.isCanBack = isCanBack;
}
@Override
protected int getLayout() {
return R.layout.dialog_loading_progress;
}
@Override
protected void initListener() {
}
protected boolean setOutside() {
return isOutSide;
}
protected boolean setKeyBack() {
return isCanBack;
}
@Override
protected void initView() {
titleView = (TextView) localView.findViewById(R.id.progress_title);
if (!TextUtils.isEmpty(title)) {
titleView.setText(title);
}
}
public void showDialog() {
show();
}
@Override
public void onBackPressed() {
if (!isCanBack) {
return;
} else {
super.onBackPressed();
}
}
}
dialog_loading_progress布局文件
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:background="@drawable/dialog_loading_bg"
android:padding="10dp"
>
android:layout_width="22dp"
android:layout_height="22dp"
style="@style/style_progressbar"
android:indeterminateDuration="700"
/>
android:id="@+id/progress_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:text="加载中"
android:textSize="14sp"
android:layout_marginTop="5dp"
/>
dialog_loading_bg.xml布局文件
android:bottomLeftRadius="5dp"
android:bottomRightRadius="5dp"
android:topLeftRadius="5dp"
android:topRightRadius="5dp" />
style_progressbar的style.xml中的配置
rotate_progress.xml的anim的动画文件
android:drawable="@drawable/loading_progress"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360">
图片你可以任意找一个吧。
其实自己动手封装一些东西,不仅仅方便自己的开发,还能提高对软件架构的理解,也有利于更容易读懂安卓的源码,等等,好处多多吧。