Dialog学习之旅

来源:互联网 发布:淘宝店铺招牌设计 编辑:程序博客网 时间:2024/05/24 04:32

            从硬件控制转为自学Android开发一年多,大学时光也就这样过了,学得越多,感觉越是记忆力不好,趁着还没有忘记,把他写下来吧。

            之前使用对话框,一般都是用AlertDialog.Builder dialog = new AlertDialog.Builder dialog(this);然后用dialog.setMessage("我是一个对话框");设置对话框内容,再设置一个确定和取消按钮,然后调用show();显示出来,然后就很高兴地运行自己的程序。但是很多时候这样的对话框能满足我们的需要吗?还有只用这个方法来创建,还有其它的方法吗?

              你问过为什么不用AlertDialog,Dialog,DialogFragment来实现,想没有想过用这些来实现能创建出怎样的对话框呢?下面就讲解一下我对这几个创建对话框的理解。

              首先这几个的继承关系:AlertDialog继承于Dialog,实现了DialogInterface接口,AlertDialog.Builder是AlertDialog里面的一个内部类,DialogFragment继承于Fragment,实现了DialogInterface.OnCancelListener, 

DialogInterface.OnDismissListener两个接口,从接口字面意思可以知道是做什么用的。

              首先说AlertDialog和AlertDialog.Builder 的区别,为什么我们用AlertDialog.Builder 来创建一个对话框对象,而不用AlertDialog呢?看AlertDialog的源码就知道AlertDialog的构造函数是一个受保护的方法,是不能够直接通过new 关键字获取对象,然而AlertDialog.Builder 是AlertDialog里面的一个内部类,可以创建一个AlertDialog.Builder 对象,里面增添了很多设置对话框属性的方法,可以当成是AlertDialog类的扩展吧。然后调用AlertDialog.Builder 里面的show()方法,看一下其源码:      

                                            public AlertDialog show() {
                                                      final AlertDialog dialog = create();
                                                      dialog.show();
                                                     return dialog;
                                                     }

              这个过程是先调用create()得到一个AlertDialog对象,然后调用AlertDialog类继承下来的show();显示出来,之所以没有用AlertDialog是因为AlertDialog的构造函数是受保护的,但可以通过AlertDialog.Builder 获得。

直接用Dialog可以吗?当然可以:Dialog dg = new Dialog(this); dg.show();只不过没有内容,只显示一个白色的框。AlertDialog.Builder 和AlertDialog只是在Dialog基础上封装了更多方法而已,你可以定义个布局文件,然后调用dg.setContentView(View view),将布局文件传递进去,然后获得布局里面的组件,就可以操作它们了,当然AlertDialog.Builder也是可以得。

              这里有些人可能说用Dialog类里面的getLayoutInflater()方法获得LayoutInflater对象后用inflater()获得布局文件后,用findViewById()获得组件后并不能操作组件,之所以会这样是因为在你传给Dialog和你获得的布局文件并不是一个

   像这样写是不对的:

                                        Dialog dg = new Dialog(this); 

                                        dg.setContentView(getLayoutInflater().inflater(R.layout.alert , null));

                                         View view =getLayoutInflater().inflater(R.layout.alert , null);

                                        Button bt = (Button)view.findViewById(R.id.button);

                                        bt.setOnClickListener(new一个监听内部类);

                                       dg.show();

代码写好后发现点击Button没有反应,之所以没有反应,是因为view并非Dialog里面的那个布局文件,可以写这样的代码验证:System.out.println(getLayoutInflater().inflater(R.layout.alert , null));和System.out.println(view);看打印出来的消息你发现地址并不相同,而且没执行一次都在变,现在知道为什么了吧。正确应该这样写

                                       final View view = getLayoutInflater().inflater(R.layout.alert , null);

                                      Dialog dg = new Dialog(this); 

                                      dg.setContentView(view);

                                      Button bt = (Button)view.findViewById(R.id.button);

                                      bt.setOnClickListener(new一个监听内部类);

                                      dg.show();


           这样就可以通过布局文件来创建自己想要的对话框了,有些时候这样并不能满足我们的需求的时候,那我们就需要自定义对话框了,当然就要继承Dialog这个类了,然后创建一个对象,用show()方法展示出来。然后重写onCreate()方法,然后就和Activity差不多去写代码了。

           下面就是用DialogFragment来实现对话框,它是一个Fragment,可以重写onCreateView()这个方法,里面可以获取布局文件,然后获得组件,最后将布局文件返回,这个方法由系统调用,返回的View就是要做对话框里面要显示的布局文件,如果返回是null,那么对话框内容什么也没有。

           当然你也可以重写onCreateDialog()方法,在里面创建其它类型的Dialog,然后将其返回,那么在onCreateDialog()。里面创建一个Dialog,要么用onCreateView()返回对话框显示的视图,更多可以看Dialogs developer guide。

public class DataDialog extends DialogFragment implements TimePickerDialog.OnTimeSetListener {    //通过创建其它类型的Dialog//    @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);//        return new TimePickerDialog(getActivity(), this, hour, minute, DateFormat.is24HourFormat(getActivity()));//    }    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);    }    @Override    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {        Toast.makeText(getActivity(), "点击时间选择器", Toast.LENGTH_SHORT).show();    }    /**     *     * @param inflater     * @param container     * @param savedInstanceState     * @return 对话框需要显示的视图     */    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View view = inflater.inflate(R.layout.dialog_adduser, null);        Button ok = (Button) view.findViewById(R.id.ok);        ok.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                System.out.println("点击了ok按钮");            }        });        return view;    }}

             如果在对话框里面自定义省份和城市对应的选择器,在选择省份时,城市列表自动调整,那么可能需要使用自定义接口,利用多态来实现回调。

     还有其它封装好的对话框  像TimePickerDialog,DtaPickerDialog等

源代码http://download.csdn.net/detail/tuoguang/9259099  







0 0