五种简单Dialog的使用,以及时间,日期Dialog中onDateSet,onTimeSet被执行两次的Bug

今天放一些Dialog的小例子,共有5种基本的Dialog以及如何使用以及他们对应的回调函数的使用


---------------------------------------------------------------------------------

Xml文件,定义5个Button用来显示5种Dialog:

<Button 
        android:id="@+id/bt_common"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="普通dialog"
        android:onClick="clickButton"/>
    <Button 
        android:id="@+id/bt_progress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="进度条"
        android:onClick="clickButton"/>
    <Button 
        android:id="@+id/bt_date"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="日期dialog"
        android:onClick="clickButton"/>
    <Button 
        android:id="@+id/bt_time"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="时间dialog"
        android:onClick="clickButton"/>
    <Button 
        android:id="@+id/bt_custom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="自定义idalog"
        android:onClick="clickButton"/>

clickButton函数,里面分别用来显示5种Dialog,分开贴出来,一种一种的来看:

最普通的Dialog:


case R.id.bt_common:
			// 普通dialog
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setIcon(android.R.drawable.dialog_frame);
			builder.setTitle("提示");
			builder.setMessage("是否退出?");
			builder.setNegativeButton("取消", null);
			builder.setPositiveButton("确定", new OnClickListener() {

				@Override
				public void onClick(DialogInterface dialog, int which) {
					finish();
				}
			});
			builder.show();
			break;

普通的Dialog这样用就行了,特别简单。设置图片setIcon,设置标题内容setTitle,设置信息setMessage(就是图中主题内容),设置取消按钮与确定按钮。这里值得说一下的是setNegativeButton("取消",null);这里第二个参数也应该是监听函数,我们对取消不做任何措施,光让dialog消失就行了,所以填入null就代表着这个功能。

ProgressDialog类型的Dialog:

代码:

ProgressDialog progressDialog = new ProgressDialog(this);
			progressDialog.setIcon(R.drawable.ic_launcher);
			progressDialog.setTitle("提示");
			progressDialog.setMessage("正在拼命加载中....");
			progressDialog.setCancelable(true);
			progressDialog.show();
这种Dialog是这样直接new出来的,请注意每种dialog的名字不同以及获取对象上的区别。说一下setCancelable();这个方法,这是设置当dialog进度条显示出的时候,点击除Dialog本身之外的空白的地方这个Dialog是否会消失,设置true为可以消失,设置false为不可以。注意:如果设置为false不能取消时,请提供相应的退出方案,否则此dialog一直不能消失,用户的体验性会及恶劣。。。

DatePickerDialog类型的Dialog:

代码:

Calendar calendar = Calendar.getInstance();
			int year = calendar.get(Calendar.YEAR);
			int monthOfYear = calendar.get(Calendar.MONTH);
			int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
			DatePickerDialog datePickerDialog = new DatePickerDialog(this,
					new OnDateSetListener() {

						@Override
						public void onDateSet(DatePicker view, int year,
								int monthOfYear, int dayOfMonth) {
							String date = year + "-" + (monthOfYear + 1) + "-"
									+ dayOfMonth;
							Toast.makeText(DialogActivity.this, date,
									Toast.LENGTH_LONG).show();
							Log.i("MainActivity", "OnDateSetListener---->");
						}

					}, year, monthOfYear, dayOfMonth) <span style="color:#FF0000;">{
				@Override
				protected void onStop() {
				}
			};</span>
			datePickerDialog.show();

这种日期选择Dialog提供特别方便的选择日期的功能。Calender类不用说,常用的日期工具类。new DatePickerDialog(context, callBack, year, monthOfYear, dayOfMonth)参数列表略长,下面是每个参数的意义:

/**
             * 创建带有日期选择器的对话框
             *
             * context  上下文对象
             * callBack  OnDateSetListener监听器
             * year    默认年
             * monthOfYear 默认月份
             * dayOfMonth  默认的日期
             */

值得注意的是,在接口回调中

blic void onDateSet(DatePicker view, int year,int monthOfYear, int dayOfMonth) 
monthOfYear是0-11月份,所以需要月份数据的时候,请+1;

TimePickerDialog类型的Dialog:

代码:

SimpleDateFormat format = new SimpleDateFormat("HH-mm-ss");
			String date = format.format(new Date());
			String[] array = date.split("-");
			TimePickerDialog timePickerDialog = new TimePickerDialog(this,
					new OnTimeSetListener() {

						@Override
						public void onTimeSet(TimePicker view, int hourOfDay,
								int minute) {
							String time = hourOfDay + ":" + minute;
							Toast.makeText(DialogActivity.this, time,
									Toast.LENGTH_LONG).show();
							Log.i("MainActivity", "OnTimeSetListener---->");
						}
					}, Integer.parseInt(array[0]), Integer.parseInt(array[1]),
					true) <span style="color:#FF0000;">{
				@Override
				protected void onStop() {
				}
			}</span>;
			timePickerDialog.show();

这个时间Dialog和日期Dialog几乎一样,就不多说了,同样有标红处(<span style="color:#FF0000;"></span>扩起来的)的代码,下面会有特殊说明此处代码是什么意思。

自定义类型的Dialog:

代码:

AlertDialog.Builder builder2 = new AlertDialog.Builder(this);
			builder2.setTitle("登陆");
			View view = LayoutInflater.from(this).inflate(
					R.layout.custom_dialog, null);
			etUsername = (EditText) view.findViewById(R.id.et_username);
			etPassword = (EditText) view.findViewById(R.id.et_password);
			builder2.setView(view);
			builder2.setNegativeButton("取消", null);
			builder2.setPositiveButton("登陆", new OnClickListener() {

				@Override
				public void onClick(DialogInterface dialog, int which) {
					Toast.makeText(
							DialogActivity.this,
							etPassword.getText().toString() + "\n"
									+ etUsername.getText().toString(),
							Toast.LENGTH_LONG).show();
				}
			});
			builder2.show();

可以看出来设置标题按钮这些东西基本一样,回调函数是直接的OnClickListener()。只不过将自定义的布局通过setView()设置进去了。自定义的布局文件也很简单,两个EditText,通过LayoutInflater加载进来。


上面的日期和时间Dialog有标红处的代码,其实java基础好的人可以轻松看出来,那是匿名子类的写法,目的是为了重写父类TimePickerDialog,DatePickerDialog中的onStop方法。因为在android4,.1-4.3(经过测试的版本)中存在着一个bug。我们知道点击确定的时候,会分别回调函数onDateSet()与onTimeSet()。这样点击一次按钮竟然回调两次函数,显然是不合理的。但是代码的写法上又没有什么错误,为什么会出现这个问题呢。通过查看源码得知,点击确认按钮完,dialog的onStop()会被执行,

onStop()的源码:

 @Override
    protected void onStop() {
        tryNotifyTimeSet();
        super.onStop();
    }
再查看按钮被点击时方法:

 public void onClick(DialogInterface dialog, int which) {
        tryNotifyTimeSet();
    }

同样调用了tryNotifyTimeSet(),那这个方法又是什么?

 private void tryNotifyTimeSet() {
        if (mCallback != null) {
            mTimePicker.clearFocus();
            mCallback.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
                    mTimePicker.getCurrentMinute());
        }
    }
我的天呀,可以看出来,这就是onTimeSet()回调函数被执行了两次的罪魁祸首。知道问题了就好解决了,我们在创建实例的时候加上方法体,重写里面的onStop()方法就行了。这样相当于继承了TimePickerDialog类的子类的实例,但是只使用一次,没必要真的创建一个子类,所以使用匿名的方法,屏蔽了一下这个BUG。DatePickerDialog同理。


-------------------------------------

原创,转载请说明,有些地方写的不清楚,因为时间有限,不喜勿喷 -----Ade-rui

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值