欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Androd自定义对话框Dialog视图及参数传递的实现方法

程序员文章站 2024-02-23 15:10:40
今天给大家讲讲有关自定义对话框的相关内容,前面两篇都在在利用系统提供的函数来实现对话框,但局限性太大,当我们想自己定义视图的时候,就不能利用系统函数了,就需要我们这里的自定...

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

一、雏形构建

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

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

Androd自定义对话框Dialog视图及参数传递的实现方法

1、dialog布局

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

<?xml version="1.0" encoding="utf-8"?> 
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" 
 android:id="@+id/log_in_layout" 
 android:layout_width="fill_parent" 
 android:layout_height="wrap_content" 
 android:orientation="horizontal"> 
 <imageview 
  android:layout_width="match_parent" 
  android:layout_height="100dip" 
  android:src="@drawable/animal1" 
  android:clickable="true" 
  android:layout_weight="1"/> 
 <imageview 
  android:layout_width="match_parent" 
  android:layout_height="100dip" 
  android:src="@drawable/animal2" 
  android:clickable="true" 
  android:layout_weight="1"/> 
 <imageview 
  android:layout_width="match_parent" 
  android:layout_height="100dip" 
  android:src="@drawable/animal3" 
  android:clickable="true" 
  android:layout_weight="1"/> 
 <imageview 
  android:layout_width="match_parent" 
  android:layout_height="100dip" 
  android:src="@drawable/animal4" 
  android:clickable="true" 
  android:layout_weight="1"/> 
</linearlayout> 

2、从dialog派生对话框类

有关构造函数:

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

有关oncreate()

在oncreate()时,利用layoutinflater获取我们对话框的view,然后利用setcontentview指定为我们customdialog类的布局。

public class customdialog extends dialog { 
 context mcontext; 
 public customdialog (context context){ 
  super(context); 
  mcontext = context; 
 } 
 public customdialog(context context, int theme) { 
  super(context, theme); 
  mcontext = context; 
 } 
 @override 
 protected void oncreate(bundle savedinstancestate) { 
  super.oncreate(savedinstancestate); 
  layoutinflater inflater = (layoutinflater) mcontext 
    .getsystemservice(context.layout_inflater_service); 
  view layout = inflater.inflate(r.layout.custom_dialog, null); 
  this.setcontentview(layout); 
 } 
} 

3、主函数(mainactivity)

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

mainactivity的布局:(activity_main.xml)

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" 
 xmlns:tools="http://schemas.android.com/tools" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 tools:context=".mainactivity"> 
 <button 
  android:id="@+id/btn_pop_dialog" 
  android:layout_width="fill_parent" 
  android:layout_height="wrap_content" 
  android:text="弹出对话框"/> 
</relativelayout> 

代码中的处理:(mainactivity.java)

在点击btn的时候,创建customdialog类的实例,并显示

public class mainactivity extends activity { 
 @override 
 protected void oncreate(bundle savedinstancestate) { 
  super.oncreate(savedinstancestate); 
  setcontentview(r.layout.activity_main); 
  button btn = (button)findviewbyid(r.id.btn_pop_dialog); 
  btn.setonclicklistener(new view.onclicklistener() { 
   @override 
   public void onclick(view view) { 
    customdialog dialog = new customdialog(mainactivity.this); 
    dialog.show(); 
   } 
  }); 
 } 
} 

这部分源码在文章最底部给出;

二、定义对话框样式

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

Androd自定义对话框Dialog视图及参数传递的实现方法

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

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

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

1、自定义样式

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

Androd自定义对话框Dialog视图及参数传递的实现方法

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

<style name="dialog" parent="android:theme.dialog"> 
 <item name="android:windowframe">@null</item> 
 <item name="android:windowisfloating">true</item> 
 <item name="android:windowcontentoverlay">@null</item> 
 <item name="android:windownotitle">true</item> 
</style> 

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

android:windowframe:界面对应的前景图片;

android:windowisfloating:表示浮在屏幕上的,如果在这里使用了,整个layout就会在 屏幕中心,相当于浮在屏幕上,所以这个只适用于dialog

android:windowcontentoverlay:表示标题栏的阴影部分的样式,使用图片或者颜色

android:windownotitle:标题栏是否隐藏,这就是我们上面显示的标题栏

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

2、使用样式

方法一:

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

public class customdialog extends dialog { 
 context mcontext; 
 public customdialog(context context) { 
  super(context); 
  mcontext = context; 
 } 
 public customdialog(context context, int theme) { 
  super(context, theme); 
  mcontext = context; 
 } 
 ………… 
} 

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

Androd自定义对话框Dialog视图及参数传递的实现方法

public class mainactivity extends activity { 
 @override 
 protected void oncreate(bundle savedinstancestate) { 
  super.oncreate(savedinstancestate); 
  setcontentview(r.layout.activity_main); 
  button btn = (button)findviewbyid(r.id.btn_pop_dialog); 
  btn.setonclicklistener(new view.onclicklistener() { 
   @override 
   public void onclick(view view) { 
    customdialog dialog = new customdialog(mainactivity.this,r.style.dialog); 
    dialog.show(); 
   } 
  }); 
 } 
} 

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

方法二:

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

public class customdialog extends dialog { 
 context mcontext; 
 public customdialog(context context) { 
  super(context,r.style.dialog); 
  mcontext = context; 
 } 
 ………… 
} 

这种情况一般用在我们封装代码时,不让其它人在外部改变我们的样式时使用的。

无论使用哪种方法,我们就已经指定我我们的对话框样式,现在的效果是这样的:

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

三、参数传递

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

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

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

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

Androd自定义对话框Dialog视图及参数传递的实现方法

1、传进去

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

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

public class customdialog extends dialog{ 
 private context mcontext; 
 private string mstr; 
 public customdialog(context context, string str, int theme) { 
  super(context, theme); 
  mcontext = context; 
  mstr = str; 
 } 
 ………… 
}

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

button btn2 = (button)findviewbyid(r.id.btn_pop_dialog_2); 
btn2.setonclicklistener(new view.onclicklistener() { 
 @override 
 public void onclick(view view) { 
  customdialog dialog = new customdialog(mainactivity.this,"from btn 2",r.style.dialog); 
  dialog.show(); 
 } 
}); 

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

2、传出来

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

在对话框中:

public class customdialog extends dialog { 
 // 利用interface来构造一个回调函数 
 public interface icustomdialogeventlistener { 
  public void customdialogevent(int valueyouwanttosendbacktotheactivity); 
 } 
 private icustomdialogeventlistener oncustomdialogeventlistener; 
 // 在构造函数中,设置进去回调函数 
 public customdialog(context context, 
      icustomdialogeventlistener oncustomdialogeventlistener) { 
  super(context); 
  this.oncustomdialogeventlistener = oncustomdialogeventlistener; 
 } 
 //当你想把值传回去的时候,调用回调函数将值设置进去 
 @override 
 public void oncreate(bundle savedinstancestate) 
 { 
  button btnok = (button) findviewbyid(r.id.customdialogbutton); 
  btnok.setonclicklistener( new button.onclicklistener() 
  { 
   public void onclick(view v) { 
    oncustomdialogeventlistener.customdialogevent(valueyouwanttosendbacktotheactivity); 
    dismiss(); 
   } 
  }); 
 } 
} 

在构造对话框时:

final customdialog dialog = new customdialog(this, new icustomdialogeventlistener() { 
 public void customdialogevent(int value) { 
  //在这里就获取到了从对话框传回来的值 
 } 
}); 

大致使用流程就是这样的,下面就把我们上面的效果利用回调函数实现出来;
首先在对话框中新建一个回调函数(接口),并且在对话框的构造方法中把回调函数传进来:

public class customdialog extends dialog implements view.onclicklistener { 
 //增加一个回调函数,用以从外部接收返回值 
 public interface icustomdialogeventlistener { 
  public void customdialogevent(int id); 
 } 
 private icustomdialogeventlistener mcustomdialogeventlistener; 
 private context mcontext; 
 private string mstr; 
 //把回调函数传进来 
 public customdialog(context context, string str, icustomdialogeventlistener listener, int theme) { 
  super(context, theme); 
  mcontext = context; 
  mstr = str; 
  mcustomdialogeventlistener = listener; 
 } 
 ………… 
} 

然后在oncreate() 函数中设定imageview的点击事件,我们将customdialog类继承view.onclicklistener接口,对点击事件统一处理:

private void bindimageclickevent(view layout){ 
 imageview img1 = (imageview)layout.findviewbyid(r.id.dialog_image1); 
 imageview img2 = (imageview)layout.findviewbyid(r.id.dialog_image2); 
 imageview img3 = (imageview)layout.findviewbyid(r.id.dialog_image3); 
 imageview img4 = (imageview)layout.findviewbyid(r.id.dialog_image4); 
 img1.setonclicklistener(this); 
 img2.setonclicklistener(this); 
 img3.setonclicklistener(this); 
 img4.setonclicklistener(this); 
} 
@override 
protected void oncreate(bundle savedinstancestate) { 
 super.oncreate(savedinstancestate); 
 layoutinflater inflater = (layoutinflater) mcontext 
   .getsystemservice(context.layout_inflater_service); 
 view layout = inflater.inflate(r.layout.custom_dialog, null); 
 textview tv = (textview)layout.findviewbyid(r.id.dialog_text); 
 tv.settext(mstr); 
 bindimageclickevent(layout);//绑定imageview点击事件 
 this.setcontentview(layout); 
} 

在oncreate()中,首先将传进来的string字符串设置到对话框的textview中;然后绑定各个imageview的点击事件

然后 就是在onclick中的处理:

主要是根据用户当前点击的imageview的id,把这个imageview所用的图片的drawableid返回给mainactivity,代码如下:

public void onclick(view view) { 
 int id = view.getid(); 
 int drawableid = -1; 
 switch (id){ 
  case r.id.dialog_image1: 
   drawableid = r.drawable.animal1; 
   break; 
  case r.id.dialog_image2: 
   drawableid = r.drawable.animal2; 
   break; 
  case r.id.dialog_image3: 
   drawableid = r.drawable.animal3; 
   break; 
  case r.id.dialog_image4: 
   drawableid = r.drawable.animal4; 
   break; 
 } 
 if (drawableid != -1) { 
  mcustomdialogeventlistener.customdialogevent(drawableid); 
 } 
 dismiss(); 
} 

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

public class customdialog extends dialog implements view.onclicklistener{ 
 //增加一个回调函数,用以从外部接收返回值 
 public interface icustomdialogeventlistener { 
  public void customdialogevent(int id); 
 } 
 private icustomdialogeventlistener mcustomdialogeventlistener; 
 private context mcontext; 
 private string mstr; 
 public customdialog(context context) { 
  super(context); 
  mcontext = context; 
 } 
 public customdialog(context context, string str,icustomdialogeventlistener listener,int theme) { 
  super(context, theme); 
  mcontext = context; 
  mstr = str; 
  mcustomdialogeventlistener = listener; 
 } 
 private void bindimageclickevent(view layout){ 
  imageview img1 = (imageview)layout.findviewbyid(r.id.dialog_image1); 
  imageview img2 = (imageview)layout.findviewbyid(r.id.dialog_image2); 
  imageview img3 = (imageview)layout.findviewbyid(r.id.dialog_image3); 
  imageview img4 = (imageview)layout.findviewbyid(r.id.dialog_image4); 
  img1.setonclicklistener(this); 
  img2.setonclicklistener(this); 
  img3.setonclicklistener(this); 
  img4.setonclicklistener(this); 
 } 
 @override 
 protected void oncreate(bundle savedinstancestate) { 
  super.oncreate(savedinstancestate); 
  layoutinflater inflater = (layoutinflater) mcontext 
    .getsystemservice(context.layout_inflater_service); 
  view layout = inflater.inflate(r.layout.custom_dialog, null); 
  textview tv = (textview)layout.findviewbyid(r.id.dialog_text); 
  tv.settext(mstr); 
  bindimageclickevent(layout); 
  this.setcontentview(layout); 
 } 
 @override 
 public void onclick(view view) { 
  int id = view.getid(); 
  int drawableid = -1; 
  switch (id){ 
   case r.id.dialog_image1: 
    drawableid = r.drawable.animal1; 
    break; 
   case r.id.dialog_image2: 
    drawableid = r.drawable.animal2; 
    break; 
   case r.id.dialog_image3: 
    drawableid = r.drawable.animal3; 
    break; 
   case r.id.dialog_image4: 
    drawableid = r.drawable.animal4; 
    break; 
  } 
  if (drawableid != -1) { 
   mcustomdialogeventlistener.customdialogevent(drawableid); 
  } 
  dismiss(); 
 } 
} 

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

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

button btn = (button)findviewbyid(r.id.btn_pop_dialog_1); 
btn.setonclicklistener(new view.onclicklistener() { 
 @override 
 public void onclick(view view) { 
  customdialog dialog = new customdialog(mainactivity.this,"from btn 1",new customdialog.icustomdialogeventlistener() { 
   @override 
   public void customdialogevent(int id) { 
    imageview imageview = (imageview)findviewbyid(r.id.main_image); 
    imageview.setimagedrawable(getresources().getdrawable(id)); 
   } 
  },r.style.dialog); 
  dialog.show(); 
 } 
}); 

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

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