Android官方推荐使用DialogFragment替换AlertDialog
DialogFragment是在Android3.0(API level 11)中引入的,它代替了已经不建议使用的AlertDialog。
DialogFragment高效地封装和管理对话框的生命周期,并让Fragment和它包含的对话框的状态保持一致。那么,已经有了AlertDialog为什么要引入DialogFragment呢?
DialogFragment对话框出现的意义
为什么android系统有AlertDialog,PopupWindow,这些完全可以满足基本客户需求,为什么还要跑出一个DialogFragment对话框呢?这就要从DialogFragment的优点说起了:
- 它和Fragment基本一致的生命周期,因此便于Activity更好的控制管理DialogFragment。
- 随屏幕旋转(横竖屏幕切换)DialogFragment对话框随之自动调整对话框大小。而AlertDialog和PopupWindow随屏幕切换而消失,并且如果处理不当很可能引发异常。
- DialogFragment的出现完美的解决了横竖屏幕切换Dialog消失的问题。
【注】以上两种方法创建对话框时候只能使用其中一种,不能两个同时使用。
首先讲第一个方法:onCreateDialog(Bundle savedInstanceState)
先看看效果图吧:
上面这个效果就充分说明了DialogFragment可以很好的解决屏幕旋转的问题。
代码也非常简单:
首先继承DialogFragment实现onCreateDialog方法:
public class AlertDialogFragment2 extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity()).setTitle("Title").setMessage("are you ok?")
.setPositiveButton("Sure", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dismiss();
}
}).setNegativeButton("cancel", null)
.create();
}
}
然后在Activity中使用它:
public void showDialogFragment(){
FragmentTransaction mFragTransaction = getFragmentManager().beginTransaction();
Fragment fragment = getFragmentManager().findFragmentByTag("dialogFragment");
if(fragment!=null){
//为了不重复显示dialog,在显示对话框之前移除正在显示的对话框
mFragTransaction.remove(fragment);
}
AlertDialogFragment2 dialogFragment = new AlertDialogFragment2();
dialogFragment.show(mFragTransaction, "dialogFragment");//显示一个Fragment并且给该Fragment添加一个Tag,可通过findFragmentByTag找到该Fragment
}
是不是很简单啊?
那么问题来了,既然是用Fragment显示对话框,那么它怎么和Activity进行通信呢?答案是使用fragment interface pattern方式。
上面的对话框好像太丑了,那么我们就像自定义AlertDialog一样使用自定义的布局,然后来说明它怎么与Activity之间的通信:
还是先看看效果图吧:
中间那段message是通过传参而改变的,然后获取到该message在Activity中显示。
效果很明显,看看代码怎么实现的吧:
AlertDialogFragment.java
public class AlertDialogFragment extends DialogFragment {
public interface DialogFragmentDataImp{//定义一个与Activity通信的接口,使用该DialogFragment的Activity须实现该接口
void showMessage(String message);
}
public static AlertDialogFragment newInstance(String message){
//创建一个带有参数的Fragment实例
AlertDialogFragment fragment = new AlertDialogFragment();
Bundle bundle = new Bundle();
bundle.putString("message", message);
fragment.setArguments(bundle);//把参数传递给该DialogFragment
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
View customView = LayoutInflater.from(getActivity()).inflate(
R.layout.base_dialogfragment, null);
Button mBtnSure = (Button) customView.findViewById(R.id.yes);
Button mBtnCancel = (Button) customView.findViewById(R.id.no);
TextView mTvMsg = (TextView) customView.findViewById(R.id.message);
mTvMsg.setText(getArguments().getString("message"));//把传递过来的数据设置给TextView
mBtnSure.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
DialogFragmentDataImp imp = (DialogFragmentDataImp) getActivity();
imp.showMessage(getArguments().getString("message"));//对话框与Activity间通信,传递数据给实现了DialogFragmentDataImp接口的Activity
dismiss();
}
});
mBtnCancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
return new AlertDialog.Builder(getActivity()).setView(customView)
.create();
}
}
再看看MainActivity.java
public class MainActivity extends ActionBarActivity implements AlertDialogFragment.DialogFragmentDataImp{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void showDialogFragment(){
FragmentTransaction mFragTransaction = getFragmentManager().beginTransaction();
Fragment fragment = getFragmentManager().findFragmentByTag("dialogFragment");
if(fragment!=null){
//为了不重复显示dialog,在显示对话框之前移除正在显示的对话框
mFragTransaction.remove(fragment);
}
AlertDialogFragment dialogFragment =AlertDialogFragment.newInstance("are you ok?");
dialogFragment.show(mFragTransaction, "dialogFragment");//显示一个Fragment并且给该Fragment添加一个Tag,可通过findFragmentByTag找到该Fragment
}
public void click(View view){
showDialogFragment();
}
@Override
public void showMessage(String message) {//实现DialogFragmentDataImp接口重写的方法
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
最后看看自定义AlertDialog的布局文件:
base_dialogfragment.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" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:textSize="20sp"
android:layout_marginLeft="50dp"
android:text="提示" />
<TextView
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="15dp"
android:textSize="15sp"
android:text="确定要退出么?" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginTop="10dp"
android:gravity="right"
android:orientation="horizontal" >
<Button
android:id="@+id/no"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:text="Cancel"
android:textColor="#ff009688"
android:textSize="12sp" />
<Button
android:id="@+id/yes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="5dp"
android:background="@null"
android:text="Sure"
android:textColor="#ff009688"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
总结:
一、我们通过定义一个DialogFragmentDataImp接口,并把activity强转为我们定义的DialogFragmentDataImp接口,然后将参数信息返回,最后让Activity实现接口里面的方法,从而得到返回而来的message,这就是和Activity之间的通信。
二、我们定义了一个newInstance(String message)方法,目地是解决DialogFragment需要使用从Activity传过来的信息的情况,通过fragment.setArguments(bundle)将信息传递给DialogFragment,通过getArguments().getString("message")从DialogFragment中取出信息以便使用。
三、
public void showDialogFragment(){
FragmentTransaction mFragTransaction = getFragmentManager().beginTransaction();
Fragment fragment = getFragmentManager().findFragmentByTag("dialogFragment");
if(fragment!=null){
//为了不重复显示dialog,在显示对话框之前移除正在显示的对话框
mFragTransaction.remove(fragment);
}
AlertDialogFragment dialogFragment =AlertDialogFragment.newInstance("are you ok?");
dialogFragment.show(mFragTransaction, "dialogFragment");//显示一个Fragment并且给该Fragment添加一个Tag,可通过findFragmentByTag找到该Fragment
}
这段代码中,可以保证每次只弹出一个对话框。
好了,第一个方法就说到这里了。
现在讲第二个方法:onCreateView(LayoutInflater,
ViewGroup, Bundle)
我相信这个方法大家并不陌生,因为用过Fragment的都知道,这是为Fragment绑定UI的方法,那么就很容易了,还是按原样的使用,加载一个布局xml文件,然后返回即ok。
还是使用刚刚的布局base_dialogfragment.xml,好,我们先贴代码:
public class BaseDialogFragment extends DialogFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.base_dialogfragment, container);
//view.findViewById(...)
return view;
}
}
就是如此简单,然后在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官方推荐使用DialogFragment替换AlertDialog的更多相关文章
- Android开发——官方推荐使用DialogFragment替换AlertDialog
)比如当屏幕旋转时,AlertDialog会消失,更不会保存如EditText上的文字,如果处理不当很可能引发异常,因为Activity销毁前不允许对话框未关闭.而DialogFragment对话框会 ...
- [Android Pro] Android 官方推荐 : DialogFragment 创建对话框
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37815413 1. 概述 DialogFragment在android 3.0时 ...
- 转帖:Android 官方推荐 : DialogFragment 创建对话框
转: Android 官方推荐 : DialogFragment 创建对话框 复制内容,留作备份 1. 概述 DialogFragment在android 3.0时被引入.是一种特殊的Fragment ...
- Android 官方推荐 : DialogFragment 创建对话框
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37815413 1. 概述 DialogFragment在android 3.0时 ...
- Android代码内存优化建议-Android官方篇
转自:http://androidperformance.com/ http://developer.android.com/intl/zh-cn/training/displaying-bitmap ...
- Android ActionBar完全解析,使用官方推荐的最佳导航栏(下) .
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/25466665 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工 ...
- Android ActionBar完全解析,使用官方推荐的最佳导航栏(上)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/18234477 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工 ...
- Android ActionBar全然解析,使用官方推荐的最佳导航栏(上)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/18234477 本篇文章主要内容来自于Android Doc.我翻译之后又做了些加工 ...
- 【转】Android ActionBar完全解析,使用官方推荐的最佳导航栏(上)
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/18234477 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工 ...
随机推荐
- 【以2-SAT为主题的婚礼UVA11294】
·新娘头饰复杂,这个婚礼怪异非凡. ·英文题,述大意: 婚宴上,有一个很长的桌子.桌子两边坐人(即人们坐成两排).新娘坐在其中一排,只能看见桌子对面所有的人.输入的m表示有m对人打过架. ...
- 初遇 Asp.net MVC 数据库依赖缓存那些事儿
问题背景: 最近做一个非常简单的功能,就是使用ajax请求的方式从服务端请求一段下拉表的数据. 以前也有做过这个功能,只不过这次做这个功能的时候冒出了一个想法: 我请求的这段数据它是一段相对比较固定的 ...
- Linux允许、禁止ping包
默认情况下Linux系统允许ping,但是在某些情况下为了安全起见,我们都把服务器设置为禁ping 临时允许ping命令可使用命令: echo 0 >/proc/sys/net/ipv4/ic ...
- Eclipse插件安装4种方法
第一种:直接复制法 假设Eclipse的安装目录在C:\eclipse,解压下载的eclipse 插件或者安装eclipse 插件到指定目录AA(如:c:\AA)文件夹,打开AA 文件夹,在AA文件夹 ...
- Mysql根据一个基库生成其他库与其不同的库升级脚本
今天研究了一下不同数据库之间如何做同步.弄了一个升级工具类,希望以后还能有所帮助. public class UpgradeDataBase { public static void main(Str ...
- 吴恩达深度学习第4课第3周编程作业 + PIL + Python3 + Anaconda环境 + Ubuntu + 导入PIL报错的解决
问题描述: 做吴恩达深度学习第4课第3周编程作业时导入PIL包报错. 我的环境: 已经安装了Tensorflow GPU 版本 Python3 Anaconda 解决办法: 安装pillow模块,而不 ...
- ubuntu 卸载从源码安装的 emacs
由于配置问题想卸了重装. 解压并进入你的源码所在目录: ./configure sudo make uninstall Done Reference: http://askubuntu.com/que ...
- Kinect 深度图像格式
Kinect的深度图像有16bit,2byte,如图: 第15位:标志位,不用做深度计算 第14~3位:深度图像数据,即距离,以毫米为单位 第0~2位:深度图中人的ID(PlayerID) 深度图有两 ...
- KVM 时钟分析
1. 关于GToffset: KVM的guset时钟为gc0_COUNT 其中:mfc0 gc0_count = c0_COUNT+GToffset vcpu_run 以及 vcpu_reenter的 ...
- 守护态运行Docker容器
更多的时候,需要让 Docker 容器在后台以守护态(Daemonized)形式运行.此时,可以通过添加 -d 参数来实现. 例如下面的命令会在后台运行容器. $ sudo docker run -d ...