Android官方推荐使用DialogFragment替换AlertDialog

DialogFragment是在Android3.0(API level 11)中引入的,它代替了已经不建议使用的AlertDialog。

DialogFragment高效地封装和管理对话框的生命周期,并让Fragment和它包含的对话框的状态保持一致。那么,已经有了AlertDialog为什么要引入DialogFragment呢?

DialogFragment对话框出现的意义

为什么android系统有AlertDialog,PopupWindow,这些完全可以满足基本客户需求,为什么还要跑出一个DialogFragment对话框呢?这就要从DialogFragment的优点说起了:

  1. 它和Fragment基本一致的生命周期,因此便于Activity更好的控制管理DialogFragment。
  2. 随屏幕旋转(横竖屏幕切换)DialogFragment对话框随之自动调整对话框大小。而AlertDialog和PopupWindow随屏幕切换而消失,并且如果处理不当很可能引发异常。
  3. DialogFragment的出现完美的解决了横竖屏幕切换Dialog消失的问题。
那么怎么使用DialogFragment呢?
有两种方法:
一、通过继承DialogFragment并且实现它的onCreateDialog(Bundle savedInstanceState)方法来创建一个DialogFragment,这个方法返回的是一个Dialog,意味着我们需要创建一个AlertDialog,并返回。
二、 通过继承DialogFragment并且实现它的onCreateView(LayoutInflater, ViewGroup, Bundle) 这个方法来加载一个我们指定的xml布局从而提供对话框内容。

【注】以上两种方法创建对话框时候只能使用其中一种,不能两个同时使用。

首先讲第一个方法:onCreateDialog(Bundle savedInstanceState)

先看看效果图吧:


上面这个效果就充分说明了DialogFragment可以很好的解决屏幕旋转的问题。

代码也非常简单:

首先继承DialogFragment实现onCreateDialog方法:

[java]  view plain  copy
 print ?
  1. public class AlertDialogFragment2 extends DialogFragment {  
  2.     @Override  
  3.     public Dialog onCreateDialog(Bundle savedInstanceState) {  
  4.         return new AlertDialog.Builder(getActivity()).setTitle("Title").setMessage("are you ok?")  
  5.           .setPositiveButton("Sure"new OnClickListener() {  
  6.               
  7.             @Override  
  8.             public void onClick(DialogInterface dialog, int which) {  
  9.                 dismiss();  
  10.             }  
  11.         }).setNegativeButton("cancel"null)  
  12.         .create();  
  13.     }  
  14. }  
然后在Activity中使用它:

[java]  view plain  copy
 print ?
  1. public void showDialogFragment(){  
  2.     FragmentTransaction mFragTransaction = getFragmentManager().beginTransaction();  
  3.     Fragment fragment =  getFragmentManager().findFragmentByTag("dialogFragment");  
  4.     if(fragment!=null){  
  5.         //为了不重复显示dialog,在显示对话框之前移除正在显示的对话框  
  6.         mFragTransaction.remove(fragment);  
  7.     }  
  8.     AlertDialogFragment2 dialogFragment = new AlertDialogFragment2();  
  9.     dialogFragment.show(mFragTransaction, "dialogFragment");//显示一个Fragment并且给该Fragment添加一个Tag,可通过findFragmentByTag找到该Fragment  
  10. }  
是不是很简单啊?

那么问题来了,既然是用Fragment显示对话框,那么它怎么和Activity进行通信呢?答案是使用fragment interface pattern方式。

上面的对话框好像太丑了,那么我们就像自定义AlertDialog一样使用自定义的布局,然后来说明它怎么与Activity之间的通信:

还是先看看效果图吧:

中间那段message是通过传参而改变的,然后获取到该message在Activity中显示。


效果很明显,看看代码怎么实现的吧:

AlertDialogFragment.java

[java]  view plain  copy
 print ?
  1. public class AlertDialogFragment extends DialogFragment {  
  2.       
  3.     public interface DialogFragmentDataImp{//定义一个与Activity通信的接口,使用该DialogFragment的Activity须实现该接口  
  4.         void showMessage(String message);  
  5.     }  
  6.       
  7.     public static AlertDialogFragment newInstance(String message){  
  8.         //创建一个带有参数的Fragment实例  
  9.         AlertDialogFragment fragment = new AlertDialogFragment();  
  10.         Bundle bundle = new Bundle();  
  11.         bundle.putString("message", message);  
  12.         fragment.setArguments(bundle);//把参数传递给该DialogFragment  
  13.         return fragment;  
  14.     }  
  15.       
  16.     @Override  
  17.     public Dialog onCreateDialog(Bundle savedInstanceState) {  
  18.         View customView = LayoutInflater.from(getActivity()).inflate(  
  19.                 R.layout.base_dialogfragment, null);  
  20.         Button mBtnSure = (Button) customView.findViewById(R.id.yes);  
  21.         Button mBtnCancel = (Button) customView.findViewById(R.id.no);  
  22.         TextView mTvMsg = (TextView) customView.findViewById(R.id.message);  
  23.           
  24.         mTvMsg.setText(getArguments().getString("message"));//把传递过来的数据设置给TextView  
  25.         mBtnSure.setOnClickListener(new OnClickListener() {  
  26.             @Override  
  27.             public void onClick(View v) {  
  28.                 DialogFragmentDataImp imp = (DialogFragmentDataImp) getActivity();  
  29.                 imp.showMessage(getArguments().getString("message"));//对话框与Activity间通信,传递数据给实现了DialogFragmentDataImp接口的Activity  
  30.                 dismiss();  
  31.             }  
  32.         });  
  33.         mBtnCancel.setOnClickListener(new OnClickListener() {  
  34.             @Override  
  35.             public void onClick(View v) {  
  36.                 dismiss();  
  37.             }  
  38.         });  
  39.         return new AlertDialog.Builder(getActivity()).setView(customView)  
  40.                 .create();  
  41.     }  
  42.   
  43. }  
再看看MainActivity.java

[java]  view plain  copy
 print ?
  1. public class MainActivity extends ActionBarActivity implements AlertDialogFragment.DialogFragmentDataImp{  
  2.   
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.activity_main);  
  7.     }  
  8.     public void showDialogFragment(){  
  9.         FragmentTransaction mFragTransaction = getFragmentManager().beginTransaction();  
  10.         Fragment fragment =  getFragmentManager().findFragmentByTag("dialogFragment");  
  11.         if(fragment!=null){  
  12.             //为了不重复显示dialog,在显示对话框之前移除正在显示的对话框  
  13.             mFragTransaction.remove(fragment);  
  14.         }  
  15.         AlertDialogFragment dialogFragment =AlertDialogFragment.newInstance("are you ok?");  
  16.         dialogFragment.show(mFragTransaction, "dialogFragment");//显示一个Fragment并且给该Fragment添加一个Tag,可通过findFragmentByTag找到该Fragment  
  17.     }  
  18.     public void click(View view){  
  19.         showDialogFragment();  
  20.     }  
  21.     @Override  
  22.     public void showMessage(String message) {//实现DialogFragmentDataImp接口重写的方法  
  23.     Toast.makeText(this, message, Toast.LENGTH_SHORT).show();  
  24.           
  25.     }  
  26. }  
最后看看自定义AlertDialog的布局文件:

base_dialogfragment.xml

[html]  view plain  copy
 print ?
  1. xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <TextView  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:layout_marginTop="15dp"  
  11.         android:textSize="20sp"  
  12.         android:layout_marginLeft="50dp"  
  13.         android:text="提示" />  
  14.   
  15.     <TextView  
  16.         android:id="@+id/message"  
  17.         android:layout_width="wrap_content"  
  18.         android:layout_height="wrap_content"  
  19.         android:layout_gravity="center"  
  20.         android:layout_marginTop="15dp"  
  21.         android:textSize="15sp"  
  22.         android:text="确定要退出么?" />  
  23.   
  24.     <LinearLayout  
  25.         android:layout_width="match_parent"  
  26.         android:layout_height="wrap_content"  
  27.         android:layout_gravity="right"  
  28.         android:layout_marginTop="10dp"  
  29.         android:gravity="right"  
  30.         android:orientation="horizontal" >  
  31.   
  32.         <Button  
  33.             android:id="@+id/no"  
  34.             android:layout_width="wrap_content"  
  35.             android:layout_height="wrap_content"  
  36.             android:background="@null"  
  37.             android:text="Cancel"  
  38.             android:textColor="#ff009688"  
  39.             android:textSize="12sp" />  
  40.   
  41.         <Button  
  42.             android:id="@+id/yes"  
  43.             android:layout_width="wrap_content"  
  44.             android:layout_height="wrap_content"  
  45.             android:layout_marginRight="5dp"  
  46.             android:background="@null"  
  47.             android:text="Sure"  
  48.             android:textColor="#ff009688"  
  49.             android:textSize="12sp" />  
  50.     LinearLayout>  
  51.   
  52. LinearLayout>  
总结:

一、我们通过定义一个DialogFragmentDataImp接口,并把activity强转为我们定义的DialogFragmentDataImp接口,然后将参数信息返回,最后让Activity实现接口里面的方法,从而得到返回而来的message,这就是和Activity之间的通信。

二、我们定义了一个newInstance(String message)方法,目地是解决DialogFragment需要使用从Activity传过来的信息的情况,通过fragment.setArguments(bundle)将信息传递给DialogFragment,通过getArguments().getString("message")从DialogFragment中取出信息以便使用。

三、

[java]  view plain  copy
 print ?
  1. public void showDialogFragment(){  
  2.         FragmentTransaction mFragTransaction = getFragmentManager().beginTransaction();  
  3.         Fragment fragment =  getFragmentManager().findFragmentByTag("dialogFragment");  
  4.         if(fragment!=null){  
  5.             //为了不重复显示dialog,在显示对话框之前移除正在显示的对话框  
  6.             mFragTransaction.remove(fragment);  
  7.         }  
  8.         AlertDialogFragment dialogFragment =AlertDialogFragment.newInstance("are you ok?");  
  9.         dialogFragment.show(mFragTransaction, "dialogFragment");//显示一个Fragment并且给该Fragment添加一个Tag,可通过findFragmentByTag找到该Fragment  
  10.     }  
这段代码中,可以保证每次只弹出一个对话框。

好了,第一个方法就说到这里了。


现在讲第二个方法:onCreateView(LayoutInflater, ViewGroup, Bundle)

我相信这个方法大家并不陌生,因为用过Fragment的都知道,这是为Fragment绑定UI的方法,那么就很容易了,还是按原样的使用,加载一个布局xml文件,然后返回即ok。

还是使用刚刚的布局base_dialogfragment.xml,好,我们先贴代码:

[java]  view plain  copy
 print ?
  1. public class BaseDialogFragment extends DialogFragment {  
  2.     @Override  
  3.     public View onCreateView(LayoutInflater inflater, ViewGroup container,  
  4.             Bundle savedInstanceState) {  
  5.         View view = inflater.inflate(R.layout.base_dialogfragment, container);  
  6.         //view.findViewById(...)  
  7.         return view;  
  8.     }  
  9.   
  10. }  
就是如此简单,然后在MainActivity中显示和前面的方法一样,就不贴了。好,我们来看看效果图:


我擦,对话框怎么多了一个标题部分啊,好丑啊,明明自定义的布局文件中没有啊?别忘了,我们继承的可是一个DialogFragment啊,那么去看看它的源码吧,发现它内部是通过mDialog.setContentView(view);意思就是把我们自定义好的布局xml文件加载到Dialog的Content内容区域了,那么它的标题当然还是有啊,而刚刚的第一种方法恰是通过mDialog,setView()自定义整个布局就没有标题那部分了。那么为了用户体验好点,就需要去标题了,方法是:在onCreateView(......)内使用getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);从而去除标题,或许你不想去除标题,反而想要在标题区域显示你设置的标题,那么可以使用:getDialog().setTitle("这是标题");。

好了,这时候我们看看去除标题后的效果:


好了,DialogFragment使用就是这些了。

个人建议使用onCreateDialog()来使用DialogFragment,因为它也可以自定义布局适合很多情况下的需求。而setCreateView它的显示大小会随你的布局的大小改变而改变。假如你的弹出的对话框提示的信息很短的话,比如只有几个字,那么它将会显示的很小,体验比较差。

源码下载:http://download.csdn.net/detail/u010687392/8737841


转自:http://blog.csdn.net/u010687392

你可能感兴趣的:(android,android优化,dialog,android,优化,android,dialog)