详解Dialog(三)——自定义对话框视图及参数传递

来源:互联网 发布:生物多样性数据 编辑:程序博客网 时间:2024/06/15 02:26


目录(?)[+]

  1. 一雏形构建
    1. Dialog布局
    2. 从Dialog派生对话框类
    3. 主函数MainActivity
  2. 二定义对话框样式
    1. 自定义样式
    2. 使用样式
  3. 三参数传递
    1. 传进去
    2. 传出来

前言:这篇文章是有关对话框的最后一篇了,最近工作是很忙,不过闲下来的时候也不想写博客,估计是累过头了,还好以前定了个任务,每个月必须写四篇,这才强制自己去一直更新,马总说过,梦想这东西还是要有的,万一实现了呢,趁在阿里的两年,努力!

相关文章:

1、《详解Dialog(一)——基础元素构建》
2、《详解Dialog(二)——有关列表的构建》
3、《详解Dialog(三)——自定义对话框视图及参数传递》


今天给大家讲讲有关自定义对话框的相关内容,前面两篇都在在利用系统提供的函数来实现对话框,但局限性太大,当我们想自己定义视图的时候,就不能利用系统函数了,就需要我们这里的自定义对话框了,有关自定义对话框的东东,以前有写过一篇《android之Dialog相关》,写的不好,今天给大家重新写一篇


一、雏形构建

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

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


1、Dialog布局

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

[html] view plain copy print?在CODE上查看代码片派生到我的代码片
  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类的布局。
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  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.         View layout = inflater.inflate(R.layout.custom_dialog, null);  
  19.         this.setContentView(layout);  
  20.     }  
  21. }  

3、主函数(MainActivity)

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

MainActivity的布局:(activity_main.xml)

[html] view plain copy print?在CODE上查看代码片派生到我的代码片
  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类的实例,并显示

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  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.         btn.setOnClickListener(new View.OnClickListener() {  
  10.             @Override  
  11.             public void onClick(View view) {  
  12.                 CustomDialog dialog = new  CustomDialog(MainActivity.this);  
  13.                 dialog.show();  
  14.             }  
  15.         });  
  16.     }  
  17.   
  18. }  
这部分源码在文章最底部给出;

二、定义对话框样式

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


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

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

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

1、自定义样式

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


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

[html] view plain copy print?在CODE上查看代码片派生到我的代码片
  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、使用样式

方法一:

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

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  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样式,所以第一种使用样式的方法是在构造时直接将样式传进来,如果这样使用,那我们在构造对话框时应该是这样的“:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  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.         btn.setOnClickListener(new View.OnClickListener() {  
  10.             @Override  
  11.             public void onClick(View view) {  
  12.                 CustomDialog dialog = new  CustomDialog(MainActivity.this,R.style.dialog);  
  13.                 dialog.show();  
  14.             }  
  15.         });  
  16.     }  
  17. }  
即在新建CustomDialog实例时,第二个参数传进来我们上面定义的样式。

方法二:

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

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  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. }  
这种情况一般用在我们封装代码时,不让其它人在外部改变我们的样式时使用的。
无论使用哪种方法,我们就已经指定我我们的对话框样式,现在的效果是这样的:


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

三、参数传递

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

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

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

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


1、传进去

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

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

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  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. }  
在使用的时候,也很简单:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  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.         CustomDialog dialog = new  CustomDialog(MainActivity.this,"From btn 2",R.style.dialog);  
  6.         dialog.show();  
  7.     }  
  8. });  
直接利用构造函数传参即可

2、传出来

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

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

在对话框中:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  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.         btnOk.setOnClickListener( new Button.OnClickListener()  
  23.         {  
  24.             public void onClick(View v) {  
  25.                 onCustomDialogEventListener.customDialogEvent(valueYouWantToSendBackToTheActivity);  
  26.                 dismiss();  
  27.             }  
  28.         });  
  29.     }  
  30. }  
在构造对话框时:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. final CustomDialog dialog = new CustomDialog(thisnew ICustomDialogEventListener() {  
  2.     public void customDialogEvent(int value) {  
  3.         //在这里就获取到了从对话框传回来的值  
  4.     }  
  5. });  
大致使用流程就是这样的,下面就把我们上面的效果利用回调函数实现出来;

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

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  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接口,对点击事件统一处理:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  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.     img1.setOnClickListener(this);  
  7.     img2.setOnClickListener(this);  
  8.     img3.setOnClickListener(this);  
  9.     img4.setOnClickListener(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.     View layout = inflater.inflate(R.layout.custom_dialog, null);  
  19.   
  20.     TextView tv = (TextView)layout.findViewById(R.id.dialog_text);  
  21.     tv.setText(mStr);  
  22.   
  23.     bindImageClickEvent(layout);//绑定ImageView点击事件  
  24.      
  25.     this.setContentView(layout);  
  26. }  
在OnCreate()中,首先将传进来的String字符串设置到对话框的TextView中;然后绑定各个ImageView的点击事件
然后 就是在OnClick中的处理:

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

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  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. }  
这样就把对话框的构造过程讲完了,完整的对话框代码是这样的:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. public class CustomDialog extends Dialog implements View.OnClickListener{  
  2.   
  3.     //增加一个回调函数,用以从外部接收返回值  
  4.     public interface ICustomDialogEventListener {  
  5.         public void customDialogEvent(int id);  
  6. //接收Edittext和TextView的传值的时候需要将参数类型变成String id
  7.     }  
  8.   
  9.     private ICustomDialogEventListener mCustomDialogEventListener;  
  10.     private Context mContext;  
  11.     private String mStr;  
  12.   
  13.     public CustomDialog(Context context) {  
  14.         super(context);  
  15.         mContext = context;  
  16.     }  
  17.   
  18.     public CustomDialog(Context context, String str,ICustomDialogEventListener listener,int theme) {  
  19.         super(context, theme);  
  20.         mContext = context;  
  21.         mStr = str;  
  22.         mCustomDialogEventListener = listener;  
  23.     }  
  24.     private void bindImageClickEvent(View layout){  
  25.         ImageView img1 = (ImageView)layout.findViewById(R.id.dialog_image1);  
  26.         ImageView img2 = (ImageView)layout.findViewById(R.id.dialog_image2);  
  27.         ImageView img3 = (ImageView)layout.findViewById(R.id.dialog_image3);  
  28.         ImageView img4 = (ImageView)layout.findViewById(R.id.dialog_image4);  
  29.         img1.setOnClickListener(this);  
  30.         img2.setOnClickListener(this);  
  31.         img3.setOnClickListener(this);  
  32.         img4.setOnClickListener(this);  
  33.     }  
  34.   
  35.     @Override  
  36.     protected void onCreate(Bundle savedInstanceState) {  
  37.         super.onCreate(savedInstanceState);  
  38.   
  39.         LayoutInflater inflater = (LayoutInflater) mContext  
  40.                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  41.         View layout = inflater.inflate(R.layout.custom_dialog, null);  
  42.   
  43.         TextView tv = (TextView)layout.findViewById(R.id.dialog_text);  
  44.         tv.setText(mStr);  
  45.   
  46.         bindImageClickEvent(layout);  
  47.   
  48.         this.setContentView(layout);  
  49.     }  
  50.   
  51.     @Override  
  52.     public void onClick(View view) {  
  53.         int id = view.getId();  
  54.         int drawableID = -1;  
  55.         switch (id){  
  56.             case R.id.dialog_image1:  
  57.                 drawableID = R.drawable.animal1;  
  58.                 break;  
  59.             case R.id.dialog_image2:  
  60.                 drawableID = R.drawable.animal2;  
  61.                 break;  
  62.             case R.id.dialog_image3:  
  63.                 drawableID = R.drawable.animal3;  
  64.                 break;  
  65.             case R.id.dialog_image4:  
  66.                 drawableID = R.drawable.animal4;  
  67.                 break;  
  68.         }  
  69.         if (drawableID != -1) {  
  70.             mCustomDialogEventListener.customDialogEvent(drawableID);  
  71. //这段代码是传值的作用
  72.         }  
  73.         dismiss();  
  74.     }  
  75. }  
下面就是构造对话框的过程了:

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

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  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.         CustomDialog dialog = 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. });  

如果需要将Edittext的内容传传过来的话,需要将public void  customDialogEvent(int id)  变成String id

然后又edittext.setText();

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


好了,本文就到这里了,有关对话框的东东基本上都讲完了,一般还是我们自定义对话框的时间比较多,所以这里讲的啰嗦了一点;


源码分为两部分:

1、《TryDialogRudiment》:第一部分,雏形构建对应的代码;

2、《TryDialogParameter》:第二、三部分,代码合集


如果本文有帮到你,记得加关注哦

源码地址:http://download.csdn.net/detail/harvic880925/8370545
请大家尊重原创者版权,转载请标明出处:http://blog.csdn.net/harvic880925/article/details/42712777 谢谢


0 0
原创粉丝点击