Android对话框使用详解

一、dialog

对话框是提示用户做出决定或输入额外信息的小窗口。

Dialog类是对话框的基类,但应避免直接实例化Dialog,而应选择以下三种:

AlertDialog:可显示标题、最多三个按钮、可选则列表项或自定义布局;(直接在此使用Edittext可能无法输入文本,需要自定义实现Dialog)

DatePickerDialog:选择日期的预定义UI;

TimePickerDialog:选择时间的预定义UI。

建议使用DialogFragment作为对话框的容器。其提供创建对话框和管理其外观所需的所有控件,而非调用Dialog对象上的方法。

使用DialogFragment管理对话框可确保它能正确处理声明周期事件,如用户按“返回”按钮或旋转屏幕时。此外,该类还允许将对话框的UI作为嵌入式组件在较大UI中重复使用。

下面的几个例子都是使用DialogFragment作为容器。

二、AlertDialog

1.对话框Fragment

public class FireMissilesDialogFragment extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // 使用Builder方便的构建dialog
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(R.string.dialog_fire_missiles)
               .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // 确定
                   }
               })
               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // 取消
                   }
               });
        // 创建alertdialog
        return builder.create();
    }
}
此时,可以创建该fragment实例并调用show()方法显示dialog。

2.提醒对话框

对话框有三个区域:标题(可选)、内容区域(可以显示消息、列表、自定义布局)、操作按钮(不应超过三个)。

1)添加按钮:

AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// 添加按钮
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // 确定
           }
       });
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id) {
               // 取消
           }
       });
// 其他属性设置
...

// 创建dialog
AlertDialog dialog = builder.create();

2)添加单选列表

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setTitle(R.string.pick_color)
           .setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int which) {
               // which对应item的下标
           }
    });
    return builder.create();
}

3)永久性多选或单选列表

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    mSelectedItems = new ArrayList();	// 选中的列表 
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // 标题
    builder.setTitle(R.string.pick_toppings)
    // 指定列表,默认选中的item(没有默认则为null),item选中回调
           .setMultiChoiceItems(R.array.toppings, null,
                      new DialogInterface.OnMultiChoiceClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int which,
                       boolean isChecked) {
                   if (isChecked) {
                       // 如果选中item,添加到选中列表
                       mSelectedItems.add(which);
                   } else if (mSelectedItems.contains(which)) {
                       // 如果item已经存在于选中列表中,移除
                       mSelectedItems.remove(Integer.valueOf(which));
                   }
               }
           })
    // 设置按钮点击事件
           .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   // 点击确定按钮,可以回调打开dialog的组件
                   ...
               }
           })
           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   ...
               }
           });

    return builder.create();
}
单选使用setSingleChoiceItems()。

4)创建自定义布局

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // 获取LayoutInflater
    LayoutInflater inflater = getActivity().getLayoutInflater();

    // 加载并设置布局
    // 第二参数传null作为父视图,因为要在dialog布局中使用
    builder.setView(inflater.inflate(R.layout.dialog_signin, null))
    // Add action buttons
           .setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   // sign in the user ...
               }
           })
           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               public void onClick(DialogInterface dialog, int id) {
                   LoginDialogFragment.this.getDialog().cancel();
               }
           });
    return builder.create();
}
提示:如果想自定义对话框,可以对话框形式显示Activity,在清单中设置其主体为Theme.Holo.Dialog。

三、TimePickerDialog

public static class TimePickerFragment extends DialogFragment
                            implements TimePickerDialog.OnTimeSetListener {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // 使用当前时间做默认值
        final Calendar c = Calendar.getInstance();
        int hour = c.get(Calendar.HOUR_OF_DAY);
        int minute = c.get(Calendar.MINUTE);

        // 创建新TimePickerDialog实例并返回
        return new TimePickerDialog(getActivity(), this, hour, minute,
                DateFormat.is24HourFormat(getActivity()));
    }

    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
        // 当用户选择时间之后做一些操作
    }
}
只要调用DialogFragment的show()方法即可显示。

四、DatePickerDialog

public static class DatePickerFragment extends DialogFragment
                            implements DatePickerDialog.OnDateSetListener {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // 当前日期为默认日期
        final Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH);
        int day = c.get(Calendar.DAY_OF_MONTH);

        //创建DatePickerDialog实例并返回
        return new DatePickerDialog(getActivity(), this, year, month, day);
    }

    public void onDateSet(DatePicker view, int year, int month, int day) {
        // 用户选择日期后做的操作
    }
}
只要调用DialogFragment的show()方法即可显示。

五、将事件传递回对话框的宿主

public class NoticeDialogFragment extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // 构建dialog并且设置按钮点击事件
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage(R.string.dialog_fire_missiles)
               .setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // 发送确定事件回调给宿主activity
                       mListener.onDialogPositiveClick(NoticeDialogFragment.this);
                   }
               })
               .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       // 发送取消事件回调给宿主activity
                       mListener.onDialogNegativeClick(NoticeDialogFragment.this);
                   }
               });
        return builder.create();
    }

    // 创建该DialogFragment的activity实例必须实现这个接口,以便接收事件回调。 
    public interface NoticeDialogListener { 
        public void onDialogPositiveClick(DialogFragment dialog); 
        public void onDialogNegativeClick(DialogFragment dialog);
    } 
    // 使用该接口示例传递事件 
    NoticeDialogListener mListener; 
    // 重写Fragment.onAttach()方法,将activity装换为回调接口 
    @Override 
    public void onAttach(Activity activity) { 
        super.onAttach(activity); 
        // 检测activity是否实现了回调接口 
        try { 
            // 转换成回调接口,以便发送事件到宿主 
            mListener = (NoticeDialogListener) activity;
        } catch (ClassCastException e) { 
            // 如果activity没有实现回调接口,抛出异常 
            throw new ClassCastException(activity.toString() + " must implement NoticeDialogListener"); 
        }
    }
    ...
}
宿主activity实现:

public class MainActivity extends FragmentActivity
                          implements NoticeDialogFragment.NoticeDialogListener{
    ...

    public void showNoticeDialog() {
        // 创建dialog fragment实例并显示
        DialogFragment dialog = new NoticeDialogFragment();
        dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
    }

    // dialog fragment获得activity的引用通过onAttach()方法
    @Override
    public void onDialogPositiveClick(DialogFragment dialog) {
        // 确定回调
        ...
    }

    @Override
    public void onDialogNegativeClick(DialogFragment dialog) {
        // 取消回调
        ...
    }
}

六、对话框消除

点击dialog的任何按钮,系统会清除对话框。
对话框列表项被单击时,也会清除。但使用单选按钮或复选按钮时除外。可以通过DialogFragment的dismiss()方法来手动清除对话框。
如果要在对话框消失时执行特定操作,可以实现DialogFragment中的onDismiss()回调。

注意,系统会在每个调用onCancel()回调事件时调用onDismiss()。不过,如果调用了Dialog.dismiss()或DialogFragment.dismiss(),系统会调用onDismiss()但不会调用onCancel()。因此当点击确定而移除对话框时,通常一个调用dismiss();

七、dialog位置

这块是自己补上的。开发中常遇到一些指定dialog位置的需求。此时,我们可以设置其window的x,y偏移量等属性。

Window window = breedLogResultDialog.getWindow();
if (window != null) {
    WindowManager.LayoutParams lp = window.getAttributes();
    lp.x = 0;
    lp.y = -100; // 向上偏移100px
    window.setAttributes(lp);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值