相信看这篇文章的人都应该知道android中的Dialog了吧,如果对于Dialog还不是很了解可以看我之前的一篇详解文章:
Dialog详解:http://www.cnblogs.com/tianzhijiexian/p/3867731.html
随着Fragment这个类的引入,Google官方推荐大家使用DialogFragment来代替传统的Dialog,那么是不是说我们之前学习的Dialog知识都没有用处了呢?非也,新的fragment是来方便大家更好的管理和重用Dialog,之前的知识其实都是可以拿来就用的,仅仅需要少许的改变。
一、Dialog和DialogFragment的区别和优劣
新来的DialogFragment让dialog也变成了碎片,相比之前来说应该做了很多优化和处理,对于程序员来看对话框现在更加具体了,就是一个activity上的一个fragment,我们也可以用fragment的知识来管理对话框了。
我们看看之前是怎么运用对话框对象的
AlertDialog dialog = new AlertDialog.Builder(this) .setTitle("Dialog") .setMessage("thisis a dialog") .show();
如果这个时候屏幕方向发生变化,就会导致Activity重建,然后之前显示的对话框就不见了。查看log可以发现这个错误:
04-1917:30:06.999: E/WindowManager(14495): Activitycom.example.androidtest.MainActivity has leaked windowcom.android.internal.policy.impl.PhoneWindow$DecorView{42ca3c18 V.E.....R....... 0,0-1026,414} that was originally added here
当然我们也可以无视这个错误,因为程序不会因此崩溃(看来android本身就已经预料到这种情况了)。
如果我们想要在旋转屏幕的时候也能保证这个对话框显示就需要做一定的处理了,在activity要销毁前设立一个标志,看这时对话框是否是显示状态,如果是那么activity在下次建立时直接显示对话框。
在onSaveInstanceState中
@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (dialog != null && dialog.isShowing()) { outState.putBoolean("DIALOG_SHOWN", true); } }
在onCreat中
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState != null) { boolean isShown = savedInstanceState.getBoolean("DIALOG_SHOWN"); if (isShown) { AlertDialog dialog = new AlertDialog.Builder(this).setTitle("Dialog") .setMessage("thisis a dialog").show(); } } …… }
使用DialogFragment来管理对话框就不会有这种问题了,代码也少了很多的逻辑处理。当你旋转屏幕的时候,fragmentManager会自定管理DialogFragment的生命周期,如果当前已经显示在屏幕上了,那么旋转屏幕后夜会自动显示,下面就是在屏幕旋转时的log输出。
4-1917:45:41.289: D/==========(16156): MyDialogFragment : onAttach
04-1917:45:41.299: D/==========(16156): MyDialogFragment : onCreate
04-1917:45:41.299: D/==========(16156): MyDialogFragment : onCreateView
04-1917:45:41.309: D/==========(16156): MyDialogFragment : onStart
04-1917:45:50.619: D/==========(16156): MyDialogFragment : onStop
04-1917:45:50.619: D/==========(16156): third activity on destroy
04-1917:45:50.619:D/==========(16156): MyDialogFragment : onDestroyView
04-1917:45:50.619: D/==========(16156): MyDialogFragment : onDetach
04-1917:45:50.639: D/==========(16156): MyDialogFragment : onAttach
04-1917:45:50.639: D/==========(16156): MyDialogFragment : onCreate
04-1917:45:50.659: D/==========(16156): MyDialogFragment : onCreateView
04-1917:45:50.659: D/==========(16156): MyDialogFragment : onStart
Ok,当然你可以不以为然,你说我的应用就是竖着用的,旋转屏幕毕竟是小概率事件,谁会开着对话框旋转来旋转去啊。那么相信下面的好处你一定不能否定吧。
我们之前用Dialog的时候,在activity中必须要建立这个对象,而且一般我们都是需要给它放监听器的,比如下面的代码:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.guid_main);new AlertDialog.Builder(GuideActivity.this).setTitle("用户申明") .setMessage(getResources().getString(R.string.statement)) .setPositiveButton("我同意", new positiveListener()) .setNegativeButton("不同意", new negativeListener()) .setCancelable(false) .show(); }private class positiveListener implements DialogInterface.OnClickListener { @Override public void onClick(DialogInterface dialog, int which) { prefs.setIsFirstTime(false); } } private class negativeListener implements DialogInterface.OnClickListener { @Override public void onClick(DialogInterface dialog, int which) { Util.virtualHome(GuideActivity.this); } }
你会发现这么长的代码很破坏activity中的逻辑性,有木有!!!在activity中我们处理的各种控件的显示和逻辑,但对于dialog这种不属于activity并且建立和处理逻辑都自成一体的东西,我们为什么要在activity中建立呢?而且为了方便重用,我们在实际过程中基本都会建立一个dialog的工具类来做处理,所以为什么不用DialogFragment来实现呢?如果通过它来实现,我们就能很方便的进行管理对话框。
此外,当旋转屏幕和按下后退键时可以更好的管理其声明周期,它和Fragment有着基本一致的声明周期。且DialogFragment也允许开发者把Dialog作为内嵌的组件进行重用,类似Fragment(可以在大屏幕和小屏幕显示出不同的效果)。有可能我们在大屏幕上就不需要弹出一个对话框了,直接内嵌在activity界面中显示即可。这点也很赞!
二、DialogFragment的最简单用法
使用DialogFragment很简单,甚至比用Fragment还简单,因为在api中已经实现了fragment切换对象了。
1.建立一个fragment对象
package com.kale.dialogfragmenttest; import android.app.DialogFragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class MyDialogFragment extends DialogFragment{ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { System.out.println("tag = "+getTag()); // tag which is from acitivity which started this fragment return inflater.inflate(R.layout.dialog, null); } }
我们建立了一个fragment,让他继承了DialogFragment,在onCreatView中通过布局文件建立了一个view,这和fragment完全一致。
布局文件如下:
<?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" android:padding="16dp"> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" /> <EditText android:layout_marginTop="10dp" android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10"> <requestFocus /> </EditText> <Button android:id="@+id/button1" android:layout_marginTop="10dp" android:layout_gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> </LinearLayout>