一、雏形构建

先给大家看下这小节的效果图:

自定义一个对话框,内容是四个ImageView横排;

android 确定对话框的使用 android构造对话框_android

1、Dialog布局

根据上图的对话框样式,我们看一下Dialog的布局定义(custom_dialog.xml)

1. <?xml version="1.0" encoding="utf-8"?>  
2.   
3. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
4. android:id="@+id/log_in_layout"  
5. android:layout_width="fill_parent"  
6. android:layout_height="wrap_content"  
7. android:orientation="horizontal">  
8.   
9. <ImageView  
10. android:layout_width="match_parent"  
11. android:layout_height="100dip"  
12. android:src="@drawable/animal1"  
13. android:clickable="true"  
14. android:layout_weight="1"/>  
15. <ImageView  
16. android:layout_width="match_parent"  
17. android:layout_height="100dip"  
18. android:src="@drawable/animal2"  
19. android:clickable="true"  
20. android:layout_weight="1"/>  
21. <ImageView  
22. android:layout_width="match_parent"  
23. android:layout_height="100dip"  
24. android:src="@drawable/animal3"  
25. android:clickable="true"  
26. android:layout_weight="1"/>  
27. <ImageView  
28. android:layout_width="match_parent"  
29. android:layout_height="100dip"  
30. android:src="@drawable/animal4"  
31. android:clickable="true"  
32. android:layout_weight="1"/>  
33.   
34. </LinearLayout>



2、从Dialog派生对话框类

 

有关构造函数:有三种构造函数,现在我这里使用重写了两个,这里只需要使用第一个,即传进去context即可;

有关OnCreate()

在OnCreate()时,利用LayoutInflater获取我们对话框的View,然后利用SetContentView指定为我们CustomDialog类的布局。

1. public class CustomDialog extends Dialog {  
2.     Context mContext;  
3. public CustomDialog (Context context){  
4. super(context);  
5.         mContext = context;  
6.     }  
7. public CustomDialog(Context context, int theme) {  
8. super(context, theme);  
9.         mContext = context;  
10.     }  
11.   
12. @Override  
13. protected void onCreate(Bundle savedInstanceState) {  
14. super.onCreate(savedInstanceState);  
15.   
16.         LayoutInflater inflater = (LayoutInflater) mContext  
17.                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
18. null);  
19. this.setContentView(layout);  
20.     }  
21. }



3、主函数(MainActivity)

在MainActivity中,我们写一个Button,当用户点击的时候弹出我们自定义的对话框实例

MainActivity的布局:(activity_main.xml)

 

1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
2. xmlns:tools="http://schemas.android.com/tools"  
3. android:layout_width="match_parent"  
4. android:layout_height="match_parent"  
5. tools:context=".MainActivity">  
6.   
7. <Button  
8. android:id="@+id/btn_pop_dialog"  
9. android:layout_width="fill_parent"  
10. android:layout_height="wrap_content"  
11. android:text="弹出对话框"/>  
12.   
13. </RelativeLayout>



代码中的处理:(MainActivity.java)
在点击Btn的时候,创建CustomDialog类的实例,并显示

    1. public class MainActivity extends Activity {  
    2.   
    3. @Override  
    4. protected void onCreate(Bundle savedInstanceState) {  
    5. super.onCreate(savedInstanceState);  
    6.         setContentView(R.layout.activity_main);  
    7.   
    8.         Button btn = (Button)findViewById(R.id.btn_pop_dialog);  
    9. new View.OnClickListener() {  
    10. @Override  
    11. public void onClick(View view) {  
    12. new  CustomDialog(MainActivity.this);  
    13.                 dialog.show();  
    14.             }  
    15.         });  
    16.     }  
    17.   
    18. }


    二、定义对话框样式

    这里再回头看看上面弹出的对话框:

    android 确定对话框的使用 android构造对话框_java_02

    在布局中,我们只定义了一个水平布局,里面放了四个ImageView,即那四个小动物,那上面那一坨是哪来的呢(我用红笔圈出来的那块)?能不能去掉?这节,我们就说说有关样式的问题。

    第一个问题,只所有上面那一坨,是因为我们没有指定对话框样式,系统会使用默认样式,那一坨就是标题栏。

    要去掉的话,我们就需要自定义样式。

    1、自定义样式

    我们的样式是写在res/values文件夹下的style.xml文件中的,如图,如果没有style.xml,自已新建一个,位置如图:

    android 确定对话框的使用 android构造对话框_android 确定对话框的使用_03

    这里定义的样式代码是这样的:


    1. <style name="dialog" parent="android:Theme.Dialog">  
    2. <item name="android:windowFrame">@null</item>  
    3. <item name="android:windowIsFloating">true</item>  
    4. <item name="android:windowContentOverlay">@null</item>  
    5. <item name="android:windowNoTitle">true</item>  
    6. </style>


    先对这几个参数解释一下:

     

    android:windowFrame:界面对应的前景图片;
    android:windowIsFloating:表示浮在屏幕上的,如果在这里使用了,整个layout就会在 屏幕中心,相当于浮在屏幕上,所以这个只适用于dialog
    android:windowContentOverlay:表示标题栏的阴影部分的样式,使用图片或者颜色
    android:windowNoTitle:标题栏是否隐藏,这就是我们上面显示的标题栏

    有关样式的内容很多很杂,这里有篇文章大家可以参考下《Andriod中Style/Theme原理以及Activity界面文件选取过程浅析》,有机会给大家总结一下有关样式和主题的内容,到时再细讲,这里不是本篇的重点,就不再细讲了。

    2、使用样式

    方法一:

    这里有两种方法来使用样式,主要还是利用构造函数,还记得我们上面说过,对话框的两个构造函数:

    1. public class CustomDialog extends Dialog {  
    2.     Context mContext;  
    3.   
    4. public CustomDialog(Context context) {  
    5. super(context);  
    6.         mContext = context;  
    7.     }  
    8.   
    9. public CustomDialog(Context context, int theme) {  
    10. super(context, theme);  
    11.         mContext = context;  
    12.     }  
    13.   
    14.     …………  
    15. }



    看第二个就是我们的Theme样式,所以第一种使用样式的方法是在构造时直接将样式传进来,如果这样使用,那我们在构造对话框时应该是这样的“:

    1. public class MainActivity extends Activity {  
    2.   
    3. @Override  
    4. protected void onCreate(Bundle savedInstanceState) {  
    5. super.onCreate(savedInstanceState);  
    6.         setContentView(R.layout.activity_main);  
    7.   
    8.         Button btn = (Button)findViewById(R.id.btn_pop_dialog);  
    9. new View.OnClickListener() {  
    10. @Override  
    11. public void onClick(View view) {  
    12. new  CustomDialog(MainActivity.this,R.style.dialog);  
    13.                 dialog.show();  
    14.             }  
    15.         });  
    16.     }  
    17. }



    即在新建CustomDialog实例时,第二个参数传进来我们上面定义的样式。

     

    方法二:

    第二种方法,就是我们在构造时,不让别人传样式,只让传进来Context,但在内部,我们利用Super(context,theme)来指定样式,代码如下:


    1. public class CustomDialog extends Dialog {  
    2.     Context mContext;  
    3.   
    4. public CustomDialog(Context context) {  
    5. super(context,R.style.dialog);  
    6.         mContext = context;  
    7.     }  
    8.   
    9.     …………  
    10. }


    这种情况一般用在我们封装代码时,不让其它人在外部改变我们的样式时使用的。
    无论使用哪种方法,我们就已经指定我我们的对话框样式,现在的效果是这样的:

     

    android 确定对话框的使用 android构造对话框_java_04

    看到了没,上面的标题栏没了,下面再看看有关参数传递的问题

    三、参数传递

    这里涉及到两个问题:传进去和传出来;

    传进去:下面有两个按钮,当用户点第一个按钮时,在对话框中显示"From btn 1",如果用户点击第二个按钮,在对话框中显示“From btn 2”

    传出来:这四个图片都是可以点击的,当用户点击任何一个图片,把它的ID传出来,并设置到我们的MainActivity中;

    这里为了好理解,更改了对话框的布局,将水平布局改成了垂直布局。并且在MainActiviy下面加了一个ImageView.

    android 确定对话框的使用 android构造对话框_java_05

    1、传进去

    往对话框里传参数,一般就是利用构造函数来完成的,很简单,即在对话框的构造函数上加上我们自己想要传的参数,这里我们需要额外传一个字符串,来表示从哪个BTN来的。

    所以对话框的构造函数就变成了这样:

    1. public class CustomDialog extends Dialog{  
    2. private Context mContext;  
    3. private String mStr;  
    4.   
    5. public CustomDialog(Context context, String str, int theme) {  
    6. super(context, theme);  
    7.         mContext = context;  
    8.         mStr = str;  
    9.     }  
    10.   
    11.     …………  
    12. }


    在使用的时候,也很简单:

    1. Button btn2 = (Button)findViewById(R.id.btn_pop_dialog_2);  
    2. btn2.setOnClickListener(new View.OnClickListener() {  
    3. @Override  
    4. public void onClick(View view) {  
    5. new  CustomDialog(MainActivity.this,"From btn 2",R.style.dialog);  
    6.         dialog.show();  
    7.     }  
    8. });


    直接利用构造函数传参即可

     

    2、传出来

    利用构造函数传参数大家都知道,但要怎么把用户的操作信息传出来就不是那么简单了,这里就要利用回调来实现了!

     

    回调函数的使用主要依照下面这些步骤:

    在对话框中:

    1. public class CustomDialog extends Dialog {  
    2.   
    3. // 利用interface来构造一个回调函数  
    4. public interface ICustomDialogEventListener {  
    5. public void customDialogEvent(int valueYouWantToSendBackToTheActivity);  
    6.     }  
    7.   
    8. private ICustomDialogEventListener onCustomDialogEventListener;  
    9.   
    10. // 在构造函数中,设置进去回调函数  
    11. public CustomDialog(Context context,  
    12.                         ICustomDialogEventListener onCustomDialogEventListener) {  
    13. super(context);  
    14. this.onCustomDialogEventListener = onCustomDialogEventListener;  
    15.     }  
    16.   
    17. //当你想把值传回去的时候,调用回调函数将值设置进去  
    18. @Override  
    19. public void onCreate(Bundle savedInstanceState)  
    20.     {  
    21.         Button btnOk = (Button) findViewById(R.id.customDialogButton);  
    22. new Button.OnClickListener()  
    23.         {  
    24. public void onClick(View v) {  
    25.                 onCustomDialogEventListener.customDialogEvent(valueYouWantToSendBackToTheActivity);  
    26.                 dismiss();  
    27.             }  
    28.         });  
    29.     }  
    30. }



    在构造对话框时:

     

    1. final CustomDialog dialog = new CustomDialog(this, new ICustomDialogEventListener() {  
    2. public void customDialogEvent(int value) {  
    3. //在这里就获取到了从对话框传回来的值  
    4.     }  
    5. });


    大致使用流程就是这样的,下面就把我们上面的效果利用回调函数实现出来;

    首先在对话框中新建一个回调函数(接口),并且在对话框的构造方法中把回调函数传进来:

     

      1. public class CustomDialog extends Dialog implements View.OnClickListener {  
      2.   
      3. //增加一个回调函数,用以从外部接收返回值  
      4. public interface ICustomDialogEventListener {  
      5. public void customDialogEvent(int id);  
      6.     }  
      7.   
      8. private ICustomDialogEventListener mCustomDialogEventListener;  
      9. private Context mContext;  
      10. private String mStr;  
      11. //把回调函数传进来  
      12. public CustomDialog(Context context, String str, ICustomDialogEventListener listener, int theme) {  
      13. super(context, theme);  
      14.         mContext = context;  
      15.         mStr = str;  
      16.         mCustomDialogEventListener = listener;  
      17.     }  
      18.   
      19.     …………  
      20. }


      然后在OnCreate() 函数中设定ImageView的点击事件,我们将CustomDialog类继承View.OnClickListener接口,对点击事件统一处理:

        1. private void bindImageClickEvent(View layout){  
        2.     ImageView img1 = (ImageView)layout.findViewById(R.id.dialog_image1);  
        3.     ImageView img2 = (ImageView)layout.findViewById(R.id.dialog_image2);  
        4.     ImageView img3 = (ImageView)layout.findViewById(R.id.dialog_image3);  
        5.     ImageView img4 = (ImageView)layout.findViewById(R.id.dialog_image4);  
        6. this);  
        7. this);  
        8. this);  
        9. this);  
        10. }  
        11.       
        12. @Override  
        13. protected void onCreate(Bundle savedInstanceState) {  
        14. super.onCreate(savedInstanceState);  
        15.   
        16.     LayoutInflater inflater = (LayoutInflater) mContext  
        17.             .getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
        18. null);  
        19.   
        20.     TextView tv = (TextView)layout.findViewById(R.id.dialog_text);  
        21.     tv.setText(mStr);  
        22.   
        23. //绑定ImageView点击事件  
        24.      
        25. this.setContentView(layout);  
        26. }



        在OnCreate()中,首先将传进来的String字符串设置到对话框的TextView中;然后绑定各个ImageView的点击事件
        然后 就是在OnClick中的处理:

         

        主要是根据用户当前点击的ImageView的ID,把这个ImageView所用的图片的DrawableID返回给MainActivity,代码如下:


          1. public void onClick(View view) {  
          2. int id = view.getId();  
          3. int drawableID = -1;  
          4. switch (id){  
          5. case R.id.dialog_image1:  
          6.             drawableID = R.drawable.animal1;  
          7. break;  
          8. case R.id.dialog_image2:  
          9.             drawableID = R.drawable.animal2;  
          10. break;  
          11. case R.id.dialog_image3:  
          12.             drawableID = R.drawable.animal3;  
          13. break;  
          14. case R.id.dialog_image4:  
          15.             drawableID = R.drawable.animal4;  
          16. break;  
          17.     }  
          18. if (drawableID != -1) {  
          19.         mCustomDialogEventListener.customDialogEvent(drawableID);  
          20.     }  
          21.     dismiss();  
          22. }



          这样就把对话框的构造过程讲完了,完整的对话框代码是这样的:

          1. public class CustomDialog extends Dialog implements View.OnClickListener{  
          2.   
          3. //增加一个回调函数,用以从外部接收返回值  
          4. public interface ICustomDialogEventListener {  
          5. public void customDialogEvent(int id);  
          6.     }  
          7.   
          8. private ICustomDialogEventListener mCustomDialogEventListener;  
          9. private Context mContext;  
          10. private String mStr;  
          11.   
          12. public CustomDialog(Context context) {  
          13. super(context);  
          14.         mContext = context;  
          15.     }  
          16.   
          17. public CustomDialog(Context context, String str,ICustomDialogEventListener listener,int theme) {  
          18. super(context, theme);  
          19.         mContext = context;  
          20.         mStr = str;  
          21.         mCustomDialogEventListener = listener;  
          22.     }  
          23. private void bindImageClickEvent(View layout){  
          24.         ImageView img1 = (ImageView)layout.findViewById(R.id.dialog_image1);  
          25.         ImageView img2 = (ImageView)layout.findViewById(R.id.dialog_image2);  
          26.         ImageView img3 = (ImageView)layout.findViewById(R.id.dialog_image3);  
          27.         ImageView img4 = (ImageView)layout.findViewById(R.id.dialog_image4);  
          28. this);  
          29. this);  
          30. this);  
          31. this);  
          32.     }  
          33.   
          34. @Override  
          35. protected void onCreate(Bundle savedInstanceState) {  
          36. super.onCreate(savedInstanceState);  
          37.   
          38.         LayoutInflater inflater = (LayoutInflater) mContext  
          39.                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
          40. null);  
          41.   
          42.         TextView tv = (TextView)layout.findViewById(R.id.dialog_text);  
          43.         tv.setText(mStr);  
          44.   
          45.         bindImageClickEvent(layout);  
          46.   
          47. this.setContentView(layout);  
          48.     }  
          49.   
          50. @Override  
          51. public void onClick(View view) {  
          52. int id = view.getId();  
          53. int drawableID = -1;  
          54. switch (id){  
          55. case R.id.dialog_image1:  
          56.                 drawableID = R.drawable.animal1;  
          57. break;  
          58. case R.id.dialog_image2:  
          59.                 drawableID = R.drawable.animal2;  
          60. break;  
          61. case R.id.dialog_image3:  
          62.                 drawableID = R.drawable.animal3;  
          63. break;  
          64. case R.id.dialog_image4:  
          65.                 drawableID = R.drawable.animal4;  
          66. break;  
          67.         }  
          68. if (drawableID != -1) {  
          69.             mCustomDialogEventListener.customDialogEvent(drawableID);  
          70.         }  
          71.         dismiss();  
          72.     }  
          73. }


          下面就是构造对话框的过程了:

           

          在MainAcitivity中,当点击一个按钮时,new一个ICustomDialogEventListener实例来接收传过来的值;

          1. Button btn = (Button)findViewById(R.id.btn_pop_dialog_1);  
          2. btn.setOnClickListener(new View.OnClickListener() {  
          3. @Override  
          4. public void onClick(View view) {  
          5. new  CustomDialog(MainActivity.this,"From btn 1",new CustomDialog.ICustomDialogEventListener() {  
          6. @Override  
          7. public void customDialogEvent(int id) {  
          8.                 ImageView imageView = (ImageView)findViewById(R.id.main_image);  
          9.                 imageView.setImageDrawable(getResources().getDrawable(id));  
          10.             }  
          11.         },R.style.dialog);  
          12.         dialog.show();  
          13.     }  
          14. });


          在我们收到传过来的DrawableID时,把它设置gc主页面ImageVIew里显示出来,这就完成了我们上面的功能。