前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(六十六)自定义对话框

Android开发笔记(六十六)自定义对话框

作者头像
aqi00
发布2019-01-18 13:02:06
2.4K0
发布2019-01-18 13:02:06
举报
文章被收录于专栏:老欧说安卓老欧说安卓

AlertDialog

Android中最常用的对话框是AlertDialog,它可以完成常见的交互操作,如提示、确认、选择等等,然后就是进度对话框ProgressDialog(参见《Android开发笔记(四十九)异步任务处理AsyncTask》)。 AlertDialog没有公开的构造函数,必须借助于AlertDialog.Builder才能完成参数设置。Builder的常用方法如下: setIcon : 设置标题的图标。 setTitle : 设置标题的文本。 setCustomTitle : 设置自定义的标题视图。 --以上方法用于设置标题部分。注意setTitle和setCustomTitle只能设置其一,不能重复设置。 setMessage : 设置内容的文本。 setView : 设置自定义的内容视图。 setAdapter : 设置List方式的内容视图。使用较麻烦,一般不用。 setItems : 设置Spinner方式的内容视图。窗口显示与对话框模式的Spinner极为相似,没有底部的按钮,一旦选中某项就立即关闭对话框。 setSingleChoiceItems : 设置单选列表的内容视图。与setItems的区别在于有显示底部的交互按钮,并且每项右边有单选按钮。 setMultiChoiceItems : 设置多选列表的内容视图。底部有交互按钮,并且每项右边有复选按钮。 --以上方法用于设置内容部分。注意这些方法互相冲突,同时只能设置其一。 setPositiveButton : 设置肯定按钮的信息,如文本、点击监听器。 setNegativeButton : 设置否定按钮的信息,如文本、点击监听器。 setNeutralButton : 设置中性按钮的信息,如文本、点击监听器。 --以上方法用于设置交互按钮。 通过Builder设置完参数,还需调用create方法才能生成AlertDialog对象。不过要想在页面上显示AlertDialog,还得调用该对象的show方法。

Dialog

实际开发中,AlertDialog往往还是无法满足个性化的要求,比如布局不够灵活、按钮的样式无法定制等等,所以常常得自己自定义对话框。查看AlertDialog源码,发现它继承自Dialog,所以自定义对话框的思路就是基于Dialog进行拓展。下面是Dialog的常用方法: Dialog构造函数 : 可定义对话框的主题样式(样式在styles.xml中定义)。如是否有标题、是否为半透明、对话框的背景等等。 isShowing : 判断对话框是否显示。 show : 显示对话框。 hide : 隐藏对话框。 dismiss : 关闭对话框。 setCancelable : 设置对话框是否可取消。 setCanceledOnTouchOutside : 点击对话框外部区域,是否自动关闭对话框。默认会自动关闭 getWindow : 获取对话框的界面对象。 其中getWindow方法是自定义对话框的关键,首先获取到对话框所在的界面对象,才能往这个界面上添加定制视图。废话少说,直接上个自定义对话框的代码例子作为说明:

代码语言:javascript
复制
import com.example.exmdialog.R;

import android.app.Dialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.TextView;

public class CustomDialog implements OnClickListener {
	private final static String TAG = "CustomDialog";
	
	private Dialog dialog;
	private View view;
	private TextView tv_title;
	private TextView tv_message;
	private Button btn_ok;
	private OnCustomListener mOnCustomListener;

	public CustomDialog(Context context) {
		view = LayoutInflater.from(context).inflate(R.layout.dialog_custom, null);
		dialog = new Dialog(context, R.style.CustomDialog);
		tv_title = (TextView) view.findViewById(R.id.tv_title);
		tv_message = (TextView) view.findViewById(R.id.tv_message);
		btn_ok = (Button) view.findViewById(R.id.btn_ok);
		btn_ok.setOnClickListener(this);
	}
	
	public void setTitle(String title) {
		tv_title.setText(title);
	}

	public void setMessage(String message) {
		tv_message.setText(message);
	}

	public void setOnCustomListener(OnCustomListener listener) {
		mOnCustomListener = listener;
	}
	
	public interface OnCustomListener {
		public void onClick();
	}

	public void show() {
		dialog.getWindow().setContentView(view);
		dialog.getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		dialog.show();
	}

	public void dismiss() {
		if (dialog != null && dialog.isShowing()) {
			dialog.dismiss();
		}
	}

	public boolean isShowing() {
		if (dialog != null) {
			return dialog.isShowing();
		} else {
			return false;
		}
	}

	@Override
	public void onClick(View v) {
		dismiss();
		if (mOnCustomListener != null) {
			mOnCustomListener.onClick();
		}
	}

}

Window

前面自定义对话框提到getWindow可以获取界面对象Window,正好就再深入探讨一下Window类的相关用法。其实不光Dialog,连Activity都是以Window为基础,如果没有Window,Activity根本没法把视图展示在手机上。 下面是Window的几个常用方法: setContentView : 设置内容视图。这个方法是不是很熟悉?我们每天打交道的Activity,第一句就是setContentView,内部原来调用Window的同名方法:getWindow().setContentView setLayout : 设置内容视图的尺寸。 setBackgroundDrawable : 设置内容视图的背景。 getDecorView : 获取当前窗口的顶层视图,可以理解为根部视图。一个运用例子参见《Android开发笔记(十九)底部标签栏TabBar》。 getCurrentFocus : 获取当前焦点所在的视图。 findViewById : 根据资源ID获取该视图的对象。这个方法更熟悉了,Activity每个都要用上许多遍,查看Activity源码,原来该方法也是调用Window的同名方法:getWindow().findViewById requestFeature : 设置窗口的特征。这个似乎也在哪里见过,看看这里有没有《Android开发笔记(二十)顶部导航栏ActionBar》,原来Activity的requestWindowFeature方法也用了Window:getWindow().requestFeature setType : 设置窗口类型。如果要让Service弹出对话框,则必须设置为WindowManager.LayoutParams.TYPE_SYSTEM_ALERT。因为Service没有窗口,只能借用系统警告来弹窗,同时TYPE_SYSTEM_ALERT类型还得加上如下权限:

代码语言:javascript
复制
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

仿ios的滚轮对话框

自定义对话框费了许多口舌,现在说点正经的应用。玩过ios的都知道,苹果手机上有个滚轮控件很酷,比Android呆板的Spinner或AlertDialog要炫很多。不过这个滚轮控件不是本文的重点,可以利用开源代码实现滚轮,这里要做的是从页面底部弹出一个对话框,中间嵌入一个滚轮,通过滚轮来选择具体项,从而完成类似Spinner选择的功能。 滚轮的开源代码从github上找来,包名是“kankan.wheel.widget”,使用方法类似Spinner,也要设置供选择的字符串数组,以及选中的监听器。接着定义一个dialog布局文件,左上角放一个取消按钮,右上角放一个确定按钮,中间放滚轮控件。然后注册相关的事件监听器,如两个按钮的点击事件,滚轮的选中事件。最后是一些参数设置,包括标题、当前位置、文字大小、文字颜色等等。 下面记录滚轮控件的几个默认值,方便以后定制修改: 1、滚轮的默认背景,代码在WheelView.java的SHADOWS_COLORS 2、文字的默认大小和颜色,代码在AbstractWheelTextAdapter.java的DEFAULT_TEXT_SIZE和DEFAULT_TEXT_COLOR 下面是滚轮对话框的代码示例:

代码语言:javascript
复制
import com.example.exmdialog.R;

import android.app.Dialog;
import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.Window;
import android.widget.TextView;
import kankan.wheel.widget.OnWheelChangedListener;
import kankan.wheel.widget.WheelView;
import kankan.wheel.widget.adapters.ArrayWheelAdapter;

/**
 * 关系滚轮对话框
 */
public class WheelDialog implements OnWheelChangedListener, OnClickListener {

	private Dialog dialog;
	private View view;
	private Context mContext;
	private WheelView id_relation;
	private ArrayWheelAdapter<String> arrayWheelAdapter;
	private String[] relation;
	private String[] value;

	private TextView tv_cancel;
	private TextView tv_sure;
	private TextView wheelTitle;
	private int pCurrent = 0;

	public WheelDialog(Context context) {
		mContext = context;
		view = LayoutInflater.from(context).inflate(R.layout.dialog_wheel, null);
		dialog = new Dialog(context, R.style.WheelDialog);

		Window dialogWindow = dialog.getWindow();
		dialogWindow.setGravity(Gravity.BOTTOM);

		relation = context.getResources().getStringArray(R.array.relation_name);
		value = context.getResources().getStringArray(R.array.relation_value);

		tv_cancel = (TextView) view.findViewById(R.id.tv_cancel);
		tv_sure = (TextView) view.findViewById(R.id.tv_sure);
		wheelTitle = (TextView) view.findViewById(R.id.wheelTitle);
		id_relation = (WheelView) view.findViewById(R.id.id_relation);

		arrayWheelAdapter = new ArrayWheelAdapter<String>(context, relation);
		id_relation.setViewAdapter(arrayWheelAdapter);
		id_relation.addChangingListener(this);

		tv_cancel.setOnClickListener(this);
		tv_sure.setOnClickListener(this);
	}

	public void show() {
		dialog.getWindow().setContentView(view);
		dialog.getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
		dialog.show();
	}

	public void dismiss() {
		if (dialog != null && dialog.isShowing()) {
			dialog.dismiss();
		}
	}

	public boolean isShowing() {
		if (dialog != null)
			return dialog.isShowing();
		return false;
	}

	public void setCancelable(boolean flag) {
		dialog.setCancelable(flag);
	}

	public void setCancelableOnTouchOutside(boolean flag) {
		dialog.setCanceledOnTouchOutside(flag);
	}

	@Override
	public void onChanged(WheelView wheel, int oldValue, int newValue) {
		if (wheel == id_relation) {
			pCurrent = id_relation.getCurrentItem();
		}
	}

	private OnWheelChangeListener onWheelChangeListener;

	public void setOnWheelChangeListener(OnWheelChangeListener onWheelChangeListener) {
		this.onWheelChangeListener = onWheelChangeListener;
	}

	public interface OnWheelChangeListener {
		public void ScollChange(String nickname, String nickvalue);
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.tv_cancel:
			dismiss();
			break;
		case R.id.tv_sure:
			if (onWheelChangeListener != null) {
				onWheelChangeListener.ScollChange(relation[pCurrent], value[pCurrent]);
			}
			dismiss();
			break;
		default:
			break;
		}
	}

	public void setNewWheelData(String[] relation, String[] value) {
		this.relation = relation;
		this.value = value;
		arrayWheelAdapter = new ArrayWheelAdapter<String>(mContext, relation);
		id_relation.setViewAdapter(arrayWheelAdapter);
	}

	public void setWheelTitle(String title) {
		wheelTitle.setText(title);
	}

	public void setCurrentItem(int index) {
		id_relation.setCurrentItem(index);
	}

	public void setTextSize(int size) {
		arrayWheelAdapter.setTextSize(size);
	}

	public void setTextColor(int color) {
		arrayWheelAdapter.setTextColor(color);
	}
	
}

代码示例

下面是各类对话框的代码例子,包括:简单的AlertDialog、类似Spinner对话框、单选对话框、多选对话框、自定义对话框、滚轮对话框等等

代码语言:javascript
复制
import com.example.exmdialog.dialog.CustomDialog;
import com.example.exmdialog.dialog.CustomDialog.OnCustomListener;
import com.example.exmdialog.dialog.WheelDialog;
import com.example.exmdialog.dialog.WheelDialog.OnWheelChangeListener;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {

	private Button btn_wheel;
	private String[] mTypeArray = {"0", "1", "2", "3", "4", "5", "6", "7"}; 
	private String[] mEatArray = {"中式炒菜", "洋快餐", "港式茶点", 
			"自助餐", "羊肉火锅", "日韩料理", "沙县小吃", "兰州拉面"}; 
	private boolean[] mCheckedArray = {true, false, false, 
			false, false, false, true, false};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		Button btn_alert = (Button) findViewById(R.id.btn_alert);
		Button btn_alert_spinner = (Button) findViewById(R.id.btn_alert_spinner);
		Button btn_alert_single = (Button) findViewById(R.id.btn_alert_single);
		Button btn_alert_multi = (Button) findViewById(R.id.btn_alert_multi);
		Button btn_custom = (Button) findViewById(R.id.btn_custom);
		btn_wheel = (Button) findViewById(R.id.btn_wheel);
		btn_alert.setOnClickListener(this);
		btn_alert_spinner.setOnClickListener(this);
		btn_alert_single.setOnClickListener(this);
		btn_alert_multi.setOnClickListener(this);
		btn_custom.setOnClickListener(this);
		btn_wheel.setOnClickListener(this);
		initWheelDialog();
	}

	private int mPosition = 0;
	private WheelDialog mWheelDialog;
	private void initWheelDialog() {
		mWheelDialog = new WheelDialog(this);
		mWheelDialog.setWheelTitle("你要吃什么?");
		mWheelDialog.setOnWheelChangeListener(new OnWheelChangeListener() {
			public void ScollChange(String nickname, String nickvalue) {
				mPosition = Integer.parseInt(nickvalue);
				btn_wheel.setText(mEatArray[mPosition]);
				showToast("您选择的是:"+nickname+"|"+nickvalue);
			}
		});
	}
	
	private void showToast(String hint) {
		Toast.makeText(MainActivity.this, hint, Toast.LENGTH_LONG).show();
	}
	
	private void showAlert() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("今天天气真好啊");
		builder.setMessage("我们去哪里玩玩吧");
		builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				showToast("是呀,我们去吃顿大餐吧");
			}
		});
		builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				showToast("真不巧,我已经约了别人啦");
			}
		});
		builder.setNeutralButton("中立", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				showToast("嗯,今天我有事,明天可以吗");
			}
		});
		AlertDialog alert = builder.create();
		alert.show();
	}
	
	private void showAlertSpinner() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("订餐请选择");
		builder.setItems(mEatArray, new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				showToast("您选择的是"+mEatArray[which]);
			}
		});
		builder.create().show();
	}

	private int mSingleChoice = 1;
	private void showAlertSingle() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("单人订餐请选择");
		builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				showToast("您最后预订的是"+mEatArray[mSingleChoice]);
			}
		});
		builder.setSingleChoiceItems(mEatArray, mSingleChoice, new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				mSingleChoice = which;
				showToast("您选择的是"+mEatArray[which]);
			}
		});
		builder.create().show();
	}

	private void showAlertMulti() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("多人订餐请选择");
		builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				String meals = "";
				String meal = "";
				for (int i=0; i<mCheckedArray.length; i++) {
					if (mCheckedArray[i] == true) {
						if (meals.length() > 0) {
							meal = "、" + mEatArray[i];
						} else {
							meal = mEatArray[i];
						}
						meals = meals + meal;
					}
				}
				showToast("您最后预订的是:"+meals);
			}
		});
		builder.setMultiChoiceItems(mEatArray, mCheckedArray, new DialogInterface.OnMultiChoiceClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which, boolean isChecked) {
				mCheckedArray[which] = isChecked;
				showToast("您已"+(isChecked?"预订":"取消")+mEatArray[which]);
			}
		});
		builder.create().show();
	}

	@Override
	public void onClick(View v) {
		if (v.getId() == R.id.btn_alert) {
			showAlert();
		} else if (v.getId() == R.id.btn_alert_spinner) {
			showAlertSpinner();
		} else if (v.getId() == R.id.btn_alert_single) {
			showAlertSingle();
		} else if (v.getId() == R.id.btn_alert_multi) {
			showAlertMulti();
		} else if (v.getId() == R.id.btn_custom) {
			CustomDialog custom = new CustomDialog(this);
			custom.setTitle("天气冷了");
			custom.setMessage("要多穿衣服噢");
			custom.setOnCustomListener(new OnCustomListener() {
				@Override
				public void onClick() {
					showToast("您点击了自定义对话框的确定按钮");
				}
			});
			custom.show();
		} else if (v.getId() == R.id.btn_wheel) {
			mWheelDialog.setNewWheelData(mEatArray, mTypeArray);
			mWheelDialog.setCurrentItem(mPosition);
			mWheelDialog.setTextSize(20);
			mWheelDialog.setTextColor(0xff1144aa);
			mWheelDialog.show();
		}
	}

}

点击下载本文用到的自定义对话框的工程代码 点此查看Android开发笔记的完整目录

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年02月18日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • AlertDialog
  • Dialog
  • Window
  • 仿ios的滚轮对话框
  • 代码示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档