Android 开发中经常会碰到对话框的需求,总结一下我个人在工作中用到的一个dialog框架.经过大量的手机测试,其兼容性很好.
其中包含了一个核心类:
BaseDialogBuilder .java
import android.app.Dialog;
import android.content.Context;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
public class BaseDialogBuilder {
Context context;
Dialog dialog;
Button leftButton;
Button rightButton;
int dialogId;
Handler mHandler = new Handler();
OnBaseDialogButtonClickListener mButtonClickListener;
// 调节对话框的宽度
private int dip2px(Context context, float dipValue){
final float scale = context.getResources().getDisplayMetrics().widthPixels / 320.0f;
final float density = context.getResources().getDisplayMetrics().density;
Log.e("DownloadDialogbuider", "dipValue="+dipValue+",scale="+scale+",density="+density);
return (int)(dipValue*scale + 0.5f);
}
public BaseDialogBuilder(final Context context,int dialogId) {
final Dialog dialog = new Dialog(context, R.style.Dialog);
// 先设置要显示的内容
dialog.setContentView(R.layout.basedilog_builder);
int temp_width=dip2px(context, 260);
Log.e("DownloadDialogbuider", "得到的退出对话框宽度:"+temp_width);
dialog.getWindow().getAttributes().width = temp_width;
dialog.setCanceledOnTouchOutside(false);
//dialog.getWindow().setWindowAnimations(R.style.popupwindow_anim);//设置动画样式
this.dialog = dialog;
this.context = context;
this.dialogId = dialogId;
}
public BaseDialogBuilder(Context context) {
this(context, 0);
}
/**
* 设置标题
* @param title 标题内容(字符串 或者 资源id)
*/
public BaseDialogBuilder setTitle(Object title) {
TextView titleView = getView(R.id.title);
titleView.setText(parseParam(title));
this.titleView=titleView;
return this;
}
/**
* 设置中间的内容
*/
public BaseDialogBuilder setMessage(Object message) {
TextView messageView = getView(R.id.message);
messageView.setText(parseParam(message));
msgView=messageView;
return this;
}
Button left;
Button singBtn;
TextView msgView;
TextView titleView;
/**
* 设置2个按钮,第一个为左边的按钮,第二个为右边的按钮,如果设置了监听器,必须手动隐藏对话框,如果没有设置监听器,点击按钮会自动关闭对话框
* @param leftBtn
* @param rightBtn
* @param listener
* @return
*/
public BaseDialogBuilder setButtons(Object leftBtn, Object rightBtn, final OnBaseDialogButtonClickListener listener) {
// 设置左边按钮的文字
Button left = getView(R.id.left);
left.setText(parseParam(leftBtn));
// 给按钮绑定监听器
left.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(listener != null) { // 有监听器
listener.onDialogButtonClick(context, BaseDialogBuilder.this, dialog, dialogId, OnBaseDialogButtonClickListener.BUTTON_LEFT);
}else{
dialog.dismiss();
}
}
});
this.left = left;
// 设置右边按钮的文字
Button right = getView(R.id.right);
right.setText(parseParam(rightBtn));
// 给按钮绑定监听器
right.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(listener != null) { // 有监听器
listener.onDialogButtonClick(context, BaseDialogBuilder.this, dialog, dialogId, OnBaseDialogButtonClickListener.BUTTON_RIGHT);
}else{
dialog.dismiss();
}
}
});
return this;
}
public BaseDialogBuilder setSingleButton(Object leftBtn, final OnBaseDialogButtonClickListener listener) {
// 设置左边按钮的文字
Button singBtn = getView(R.id.btn_single);
singBtn.setText(parseParam(leftBtn));
// 给按钮绑定监听器
singBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(listener != null) { // 有监听器
listener.onDialogButtonClick(context, BaseDialogBuilder.this, dialog, dialogId, OnBaseDialogButtonClickListener.BUTTON_LEFT);
}else{
dialog.dismiss();
}
}
});
this.singBtn = singBtn;
return this;
}
/**
* 通过id找到对话框中对应的子控件
* @param id 子控件的id
* @return 子控件
*/
@SuppressWarnings("unchecked")
public <T extends View>T getView(int id) {
return (T) dialog.findViewById(id);
}
/**
* 解析参数
* @param param 字符串 或者 资源id
* @return 统一返回字符串
*/
private String parseParam(Object param) {
if (param instanceof Integer) {
return context.getString((Integer)param);
} else if (param instanceof String) {
return param.toString();
}
return null;
}
/**
* 说明已经确定对话框的界面参数
* @return
*/
public Dialog create() {
//是否显示Title布局
if(titleView!=null){
titleView.setVisibility(View.VISIBLE);
}
//是否显示Message布局
if(msgView!=null){
msgView.setVisibility(View.VISIBLE);
}
//是否需要单个按钮/两个按钮布局
if (left != null) { // 说明不需要按钮
// 得到按钮所在的布局
ViewGroup btnsLayout = getView(R.id.btns_layout);
btnsLayout.setVisibility(View.VISIBLE);
}else if(singBtn!=null){
ViewGroup btnsLayout = getView(R.id.single_btns_layout);
btnsLayout.setVisibility(View.VISIBLE);
}
return dialog;
}
public interface OnBaseDialogButtonClickListener {
public static final int BUTTON_LEFT = -1;
public static final int BUTTON_RIGHT = 1;
public void onDialogButtonClick(Context context,BaseDialogBuilder builder, Dialog dialog, int dialogId, int which);
}
/**
* 将view放进对话框中
*/
public BaseDialogBuilder setView(View view) {
// 1.获得message所在的布局
ViewGroup messageLayout = getView(R.id.message_layout);
// 3.添加新的View
messageLayout.addView(view);
return this;
}
/**
* 将布局文件对应的View放进对话框中
* @param layout
* @return
*/
public BaseDialogBuilder setView(int layout) {
ViewGroup parent = getView(R.id.message_layout);
View view = LayoutInflater.from(context).inflate(layout, parent, false);
return setView(view);
}
/**
* 传入一个String数组的集合,当成菜单项填充到一个ListView中,然后将ListView放到对话框的中间部分控件
* @param items
* @return
*/
/*public BaseDialgBuilder setItems(String[] items,final OnDialogItemClickListener listener){
//将指定布局文件中的ListView添加到对话框的容器中
setView(R.layout.listview);
//从布局文件中获取ListView 控件,设置参数
ListView listView=getView(android.R.id.list);
//通过适配器给listView填充数据
ArrayAdapter<String> adapter=new ArrayAdapter<String>(context, R.layout.item_contextmenu, items);
listView.setAdapter(adapter);
//给listView绑定监听器
listView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//关闭对话框
dialog.dismiss();
//回调传入的监听器的方法,将参数带出去
if(listener!=null){
listener.onDialogItemClick(context, BaseDialgBuilder.this, dialog, position) ;
}
}
});
return this;
}*/
/*public BaseDialgBuilder setItems(int resId ,final OnDialogItemClickListener listener){
this.setItems(context.getResources().getStringArray(resId),listener);
return this;
}*/
/**
* 自定义的对话框选项的单击事件监听器
* @author RH红日
*
*/
public interface OnDialogItemClickListener{
public void onDialogItemClick(Context context,BaseDialogBuilder bulder,Dialog dialog,int position);
}
}
二: 样式文件中添加一下样式 : /res/values/styles.xml
@android:color/transparent
@null
true
true
@null
三 使用:
package com.example.testdialogbuilder;
import com.example.testdialogbuilder.BaseDialogBuilder.OnBaseDialogButtonClickListener;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
public class MainActivity extends Activity implements OnClickListener{
private Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
}
private void initData() {
mContext=this;
}
//显示需要一个按钮, 需要回调的对话框
private void showSingButtonDialog() {
new BaseDialogBuilder(mContext)//
.setTitle(R.string.text_title_tip)//
.setMessage("提示内容")
.setSingleButton(R.string.ok, new OnBaseDialogButtonClickListener(){
@Override
public void onDialogButtonClick(Context context,
BaseDialogBuilder builder, Dialog dialog,
int dialogId, int which) {
switch (which) {
case OnBaseDialogButtonClickListener.BUTTON_LEFT:
Toast.makeText(mContext, "点击了左边的按钮", Toast.LENGTH_LONG).show();
break;
default:
break;
}
dialog.dismiss();
}})
.create()//
.show();
}
//显示只需要一个按钮,且不需要回调的对话框
private void showSimpleDialog() {
new BaseDialogBuilder(mContext)//
.setTitle(R.string.text_title_tip)//
.setMessage(R.string.text_no_network_tip)//
.setSingleButton(R.string.ok, null)//
.create()//
.show();
}
//显示两个按钮, 需要处理回调的对话框
private void showTwoButtonDialog() {
Dialog errorDialog = new BaseDialogBuilder(mContext)//
.setTitle(R.string.text_title_tip)
.setMessage("这是两个按钮的对话框")
.setButtons(R.string.cancel,R.string.ok,new OnBaseDialogButtonClickListener(){
@Override
public void onDialogButtonClick(Context context,
BaseDialogBuilder builder, Dialog dialog, int dialogId,int which) {
switch (which) {
case OnBaseDialogButtonClickListener.BUTTON_RIGHT:
Toast.makeText(mContext, "点击了右边的按钮", Toast.LENGTH_LONG).show();
break;
case OnBaseDialogButtonClickListener.BUTTON_LEFT:
Toast.makeText(mContext, "点击了左边的按钮", Toast.LENGTH_LONG).show();
break;
default:
break;
}
dialog.dismiss();
}
})
.create();
errorDialog.setCancelable(false);
errorDialog.show();
}
private void showUploadDiaolg() {
Dialog uploadDialog = new BaseDialogBuilder(mContext)//
.setView(R.layout.dialog_progress)
.setSingleButton(R.string.cancel, new OnBaseDialogButtonClickListener(){
@Override
public void onDialogButtonClick(Context context,
BaseDialogBuilder builder, Dialog dialog,
int dialogId, int which) {
switch (which) {
case OnBaseDialogButtonClickListener.BUTTON_LEFT:
break;
default:
break;
}
dialog.dismiss();
}})
.create();
TextView text = (TextView) uploadDialog.findViewById(R.id.showText);
text.setText("这是加载进度条对话框");
ImageView iv_icon=(ImageView) uploadDialog.findViewById(R.id.icon);
Animation animation=AnimationUtils.loadAnimation(mContext, R.anim.refresh);
animation.setInterpolator(new LinearInterpolator());
iv_icon.setAnimation(animation);
iv_icon.startAnimation(animation);
uploadDialog.setCancelable(false);
uploadDialog.show();
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_one:
showSimpleDialog();
break;
case R.id.btn_two:
showSingButtonDialog();
break;
case R.id.btn_three:
showTwoButtonDialog();
break;
case R.id.btn_four:
showUploadDiaolg();
break;
default:
break;
}
}
}