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方法是自定义对话框的关键,首先获取到对话框所在的界面对象,才能往这个界面上添加定制视图。废话少说,直接上个自定义对话框的代码例子作为说明:

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;}}@Overridepublic 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类型还得加上如下权限:

<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

下面是滚轮对话框的代码示例:

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);}@Overridepublic 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);}@Overridepublic 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对话框、单选对话框、多选对话框、自定义对话框、滚轮对话框等等

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};@Overrideprotected 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() {@Overridepublic void onClick(DialogInterface dialog, int which) {showToast("是呀,我们去吃顿大餐吧");}});builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {showToast("真不巧,我已经约了别人啦");}});builder.setNeutralButton("中立", new DialogInterface.OnClickListener() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic void onClick(DialogInterface dialog, int which) {showToast("您最后预订的是"+mEatArray[mSingleChoice]);}});builder.setSingleChoiceItems(mEatArray, mSingleChoice, new DialogInterface.OnClickListener() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic void onClick(DialogInterface dialog, int which, boolean isChecked) {mCheckedArray[which] = isChecked;showToast("您已"+(isChecked?"预订":"取消")+mEatArray[which]);}});builder.create().show();}@Overridepublic 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() {@Overridepublic 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开发笔记的完整目录

Android开发笔记(六十六)自定义对话框相关推荐

  1. Android开发笔记(十六)秋千摇摆动画SwingAnimation

    上节博主介绍了AlphaAnimation和淡入淡出动画的使用,其实AlphaAnimation只是四种补间动画中的一种.那么为了加深对其他补间动画的理解,我想说说旋转动画RotateAnimatio ...

  2. Android开发笔记(一百六十六)H5通过WebView录像上传

    前面的博文< Android开发笔记(一百五十二)H5通过WebView上传图片>介绍了如何拍照上传给网页,不料客户又要求再加个摄像上传给网页.既然如此,那么再探讨一下如何实现这个摄像上传 ...

  3. Android开发笔记(一百六十五)利用红外发射遥控电器

    红外遥控是一种无线控制技术,它具有功耗小.成本低.易实现等诸多优点,因而被各种电子设备特别是家用电器广泛采用,像日常生活中的电视遥控器.空调遥控器等等基本都采用红外遥控技术. 不过遥控器并不都是红外遥 ...

  4. Android开发笔记(一百六十四)仿京东首页的下拉刷新

    上一篇文章介绍了高仿京东的沉浸式状态栏,可是跟京东首页的头部轮播图相比,依然有三处缺憾: 1.京东的头部Banner上方,除了有悬浮着的状态栏,状态栏下面还有一行悬浮工具栏,内嵌扫一扫图标.搜索框,以 ...

  5. Android开发笔记(一百六十)休眠模式下的定时器控制

    定时器AlarmManager常常用于需要周期性处理的场合,比如闹钟提醒.任务轮询等等.并且定时器来源于系统服务,即使App已经不在运行了,也能收到定时器发出的广播而被唤醒.似此回光返照的神技,便遭到 ...

  6. Android开发笔记(一百六十二)蓝牙设备的连接与配对

    蓝牙是一种短距离无线通信技术,它由爱立信公司于1994年创制,原本想替代连接电信设备的数据线,但是后来发现它也能用于移动设备之间的数据传输,所以蓝牙技术在手机上获得了长足发展. 因为手机内部的通讯芯片 ...

  7. Android开发笔记(一百六十九)利用BottomNavigationView实现底部标签栏

    在Android Studio上创建官方默认的首屏标签页面很方便,首先右击需要添加标签栏的模块,在弹出的右键菜单中依次选择"New"--"Activity"-- ...

  8. Android开发笔记(一百六十八)为应用绑定通知渠道并展示消息角标

    为了分清消息通知的轻重缓急,从Android8开始新增了通知渠道,并且必须指定通知渠道才能正常推送消息.一个应用允许拥有多个通知渠道,每个渠道的重要性各不相同,有的渠道消息在通知栏被折叠成小行,有的渠 ...

  9. Android开发笔记(九十六)集合动画与属性动画

    集合动画AnimationSet 补间动画有四大类:透明度动画AlphaAnimation.旋转动画RotateAnimation.缩放动画ScaleAnimation.平移动画TranslateAn ...

  10. 【Visual C++】游戏开发笔记四十六 浅墨DirectX教程十四 模板测试与镜面特效专场

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处.   文章链接: http://blog.csdn.net/zhmxy555/article/details/8632184 作者:毛星云( ...

最新文章

  1. CVPR2020 best paper:对称可变形三维物体的无监督学习
  2. 2015-04-22记录--一些JS疑惑
  3. CentOS安装网络代理软件
  4. 图解 VS2015 如何打包winform 安装程序
  5. 小五思科技术学习笔记之SSH
  6. js 设备条形码字体_蚌埠食品袋激光打码机设备-青岛博泰格睿特
  7. 脚手架 - props
  8. 【java】求两个字符串的最长公共子串
  9. keil5 配置 stm32f103rc 软件仿真
  10. offset Dimensions 详解
  11. python numpy 里面的[:, None]是个什么鬼?[..., None]呢?
  12. matlab 实现差分求导,matlab循环求导
  13. 公司年会要求搞一个抽奖程序,及时安排一波
  14. 十年游戏建模师给想学次世代游戏建模同学的一些忠告,太受益了
  15. 方差公式初三_方差|初中方差的计算公式
  16. AI算法+EasyCVR打造智慧城市,构建万物互联智能世界
  17. 计算机中丢失msvcp140.dll无法启动此程序怎么办(修复教程)
  18. 物联网通信_闲聊协议
  19. 手机病毒“僵尸网络”进入高发期
  20. 工信部数字电视标准符合性检测中心发布的

热门文章

  1. TensorFlow2.0:模型的保存与加载
  2. 吴恩达机器学习:偏差与方差、欠拟合与过拟合
  3. 用JavaScript刷leetcode(刷题 第一天)
  4. 求解斐波那契第n项的几种解法(含矩阵乘法+快速幂) Python实现
  5. openresty 前端开发入门三之JSON篇
  6. 华景机器人怎么控制_【扫地机器人选购】支持华为hilink智能家居联动/支持华为小艺语音控制的扫地机器人...
  7. c++ opencv mat_图像拼接Opencv源码重构
  8. vb net excel 剪贴板 粘贴_利用剪贴板强化 Excel 计算
  9. 2的负x次幂图像_数学| NO.2,3函数 T51
  10. 家卫士扫地机器人好吗_扫地机器人哪个牌子好?市场最全智能扫地机器人品牌解析_扫地机器人...