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

详解Android应用中DialogFragment的基本用法

程序员文章站 2024-02-29 23:13:28
dialogfragment的基本用法 1. 创建dialogfragment public class dialoga extends dialogfra...

dialogfragment的基本用法
1. 创建dialogfragment

public class dialoga extends dialogfragment implements dialoginterface.onclicklistener {

 @override
 public dialog oncreatedialog(bundle savedinstancestate) {
  alertdialog.builder builder = new alertdialog.builder(getactivity());
  builder.setmessage(r.string.dialoga_title)
    .setpositivebutton(r.string.ok, this)
    .setnegativebutton(r.string.cancel, this);

  return builder.create();
 } 

 @override
 public void onclick(dialoginterface dialog, int id) {
  switch(id) {
   case alertdialog.button_negative:
    toast.maketext(getactivity(), "negative", toast.length_short).show();
    break;
   case alertdialog.button_positive:
    toast.maketext(getactivity(), "positive", toast.length_short).show();
    break;
   default:
    break;
  } 
 } 
}

说明:自定义一个dialogfragment,并重写它的oncreatedialog()方法。
2. 调用该dialogfragment
下面是在fragmentactivity中调用该dialogfragment对话框。

public class dialogtest extends fragmentactivity {

 @override
 public void oncreate(bundle savedinstancestate) {
  super.oncreate(savedinstancestate);
  setcontentview(r.layout.main);

  showdialog();
 }

 private void showdialog() {
  fragmentmanager fm = getsupportfragmentmanager();
  dialoga dialoga = new dialoga();
  dialoga.show(fm, "fragmenta");
 }
}

自定义dialogfragment布局
下面介绍自定义dialogfragment的布局的方法
点击查看:自定义dialogfragment布局的完整代码
1. 设置布局文件

<?xml version="1.0" encoding="utf-8"?>
<linearlayout 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"
 android:orientation="vertical" >

 <textview
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:hint="@string/dialoga_intro" />

 <imageview
  android:id="@+id/image"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:src="@drawable/ic_action_video" />

</linearlayout>

2. 使用布局

public class dialoga extends dialogfragment implements dialoginterface.onclicklistener {

 @override
 public dialog oncreatedialog(bundle savedinstancestate) {
  alertdialog.builder builder = new alertdialog.builder(getactivity());
  layoutinflater inflater = getactivity().getlayoutinflater();
  builder.setview(inflater.inflate(r.layout.dialoga, null))
    .setmessage(r.string.dialoga_title)
    .setpositivebutton(r.string.ok, this)
    .setnegativebutton(r.string.cancel, this);

  return builder.create();
 }

 @override
 public void onclick(dialoginterface dialog, int id) {
  switch(id) {
   case alertdialog.button_negative:
    toast.maketext(getactivity(), "negative", toast.length_short).show();
    break;
   case alertdialog.button_positive:
    toast.maketext(getactivity(), "positive", toast.length_short).show();
    break;
   default:
    break;
  }
 }
}

dialogfragment和activity的交互
下面介绍自定义dialogfragment和activity交互的方法
点击查看:dialogfragment和activity交互的完整代码
1. 定义通信接口
在dialogfragment中定义它们之间的通信接口。

public interface noticedialoglistener {
 public void ondialogpositiveclick(dialogfragment dialog);
 public void ondialognegativeclick(dialogfragment dialog);
} 

// use this instance of the interface to deliver action events
noticedialoglistener mlistener;

// override the fragment.onattach() method to instantiate the noticedialoglistener
@override
public void onattach(activity activity) {
 super.onattach(activity);
 // verify that the host activity implements the callback interface
 try {
  // instantiate the noticedialoglistener so we can send events to the host
  mlistener = (noticedialoglistener) activity;
 } catch (classcastexception e) {
  // the activity doesn't implement the interface, throw exception
  throw new classcastexception(activity.tostring()
    + " must implement noticedialoglistener");
 } 
} 

2. 在dialogfragment中调用该接口

@override
public void onclick(dialoginterface dialog, int id) {
 switch(id) {
  case alertdialog.button_positive:
   //toast.maketext(getactivity(), "negative", toast.length_short).show();
   mlistener.ondialogpositiveclick(dialoga.this);
   break;
  case alertdialog.button_negative:
   //toast.maketext(getactivity(), "positive", toast.length_short).show();
   mlistener.ondialognegativeclick(dialoga.this);
   break;
  default:
   break;
 } 
}

3. 在activity中实现该接口

public class dialogtest extends fragmentactivity 
 implements dialoga.noticedialoglistener {

 ...

 @override
 public void ondialogpositiveclick(dialogfragment dialog) {
  toast.maketext(this, "positive callback", toast.length_short).show();
 }
 @override
 public void ondialognegativeclick(dialogfragment dialog) {
  toast.maketext(this, "negative callback", toast.length_short).show();
 }
}

dialog与dialogfragment的对比
从代码的编写角度看,dialog使用起来要更为简单,但是google则是推荐尽量使用dialogfragment(对于android 3.0以下的版本,可以结合使用support包中提供的dialogfragment以及fragmentactivity)。今天试着用这两种方式来创建对话框,发现dialogfragment果然有一个非常好的特性(在手机配置变化,导致activity需要重新创建时,例如旋屏,基于dialogfragment的对话框将会由fragmentmanager自动重建,然而基于dialog实现的对话框则没有这样的能力)。

下面是两段实例代码:

他们使用的界面都一样:(dialog.xml)

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical" >
 
 <imageview
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:src="@drawable/ic_launcher" />
 
</linearlayout>

1.基于dialog实现的对话框

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

当我们点击按钮时,会弹出对话框(内容为android logo),当我们旋转屏幕后,activity重新创建,整个activity的界面没有问题,而对话框消失了。
除此之外,其实还有一个问题,就是在logcat中会看到异常信息:android..leaked .. window,这是因为在activity结束之前,android要求所有的dialog必须要关闭。我们旋屏后,activity会被重建,而上面的代码逻辑并没有考虑到对话框的状态以及是否已关闭。

于是将上述代码修改为:

public class mainactivity extends activity {
 private button clk;
 private dialog dialog;
 @override
 protected void oncreate(bundle savedinstancestate) {
  super.oncreate(savedinstancestate);
  setcontentview(r.layout.activity_main);
   
  clk = (button) findviewbyid(r.id.clk);
  dialog = new dialog(this);
  dialog.setcontentview(r.layout.dialog);
  clk.setonclicklistener(new onclicklistener() {
    
   @override
   public void onclick(view v) {
    dialog.show();
   }
  });
 
  //用户恢复对话框的状态
  if(savedinstancestate != null && savedinstancestate.getboolean("dialog_show"))
   clk.performclick();
 }
 
 /**
  * 用于保存对话框的状态以便恢复
  */
 @override
 protected void onsaveinstancestate(bundle outstate) {
  super.onsaveinstancestate(outstate);
  if(dialog != null && dialog.isshowing())
   outstate.putboolean("dialog_show", true);
  else
   outstate.putboolean("dialog_show", false);
 }
 
 /**
  * 在activity销毁之前,确保对话框以关闭
  */
 @override
 protected void ondestroy() {
  super.ondestroy();
  if(dialog != null && dialog.isshowing())
   dialog.dismiss();
 }
}


2. 基于dialogfragment的对话框

与上面的对话框使用同样的界面布局,此处仅仅展现一个简单对话框,因此只重写了oncreateview方法

public class mydialogfragment extends dialogfragment {
 @override
 public view oncreateview(layoutinflater inflater, viewgroup container,
   bundle savedinstancestate) {
  view v = inflater.inflate(r.layout.dialog, container, false);
  return v;
 }
}

public class mainactivity extends fragmentactivity {
 private button clk;
 @override
 protected void oncreate(bundle savedinstancestate) {
  super.oncreate(savedinstancestate);
  setcontentview(r.layout.activity_main);
   
  clk = (button) findviewbyid(r.id.clk);
  clk.setonclicklistener(new onclicklistener() {
    
   @override
   public void onclick(view v) {
    mydialogfragment mdf = new mydialogfragment();
    fragmenttransaction ft = getsupportfragmentmanager().begintransaction();
    ft.settransition(fragmenttransaction.transit_fragment_fade);
    mdf.show(ft, "df");
   }
  });
 }
}


这两段代码可以实现第一种方式的同样功能,此处我们并没有去关心对话框的重建,以及activity销毁前对话框是否已关闭,这一切都是由fragmentmanager来管理。
其实dialogfragment还拥有fragment的优点,即可以在一个activity内部实现回退(因为fragmentmanager会管理一个回退栈)