本文是参考ProAndroid的第10章Working with Dialogs的内容,在合适的地方添加了作者自己的一些见解最终成文。

Android 中的对话框是一个展示在当前窗口上的小一号的窗口,用于展示或接受一些信息,通常在用户关闭一个对话框时会回到原来的窗口上。例如:展示一个紧急信息,接受用户输入等;Android SDK中为对话框(Dialog)提供了丰富的实现接口。同时,Android还提供了一个嵌入到Activity中的DialogFragment 来实现对话框布局。

Android中对话框样式有提醒对话框,提示对话框,选择列表对话框,单选,多选,进度,时间和日期对话框。并且还支持自定义对话框。本章并不详细描述每种Dialog的用法,而是通过一个简单的实例来解析Dialog的底层结构,这样在有新的Dialog类型时也知道怎么用。

关于对话框有一点很重要的是,在Android 3.0 Google发布了Fragment是之后,官方实例中只有FragementDialog的示例了,及时之前的版本也可以通过支持库来实现。因此本章中重点也在DialogFragment。

1 Android中的Dialogs

Android中的对话框是异步的,如果你之前使用过同步对话框(Windows对话框,JavaScript中web对话框等)就会有直观的对比,在同步对话框中,对话框之后的代码是在对话框返回之后执行的,而异步对话框不会等待对话框返回。因此异步对话框需要根据用户具体的选择进行接口的回调。

同时,异步对话框也意味着你可以在应用进程中关闭对话框,例如在展示一个进度对话框时,当要执行的费时操作完成之后可以关闭这个进度对话框。

2 理解 Dialog Fragment

本节将会介绍使用DialogFragment来展示一个简单的提醒对话框(AlertDialog)和一个自定义文本输入对话框。

2.1 DialogFragment 基础

在使用DialogFragment之前,我们需要知道DialogFragment继承至Fragment,因此其生命周期的行为跟Fragment是一直的,要使用DialogFragment,你需要实现一个继承了DialogFragment的类。

  1. public class MyDialogFragment extends DialogFragment{... }

然后使用 fragment transaction 操作来展示这个对话框。清单 10-1 展示了其具体用法。

  1. 清单10-1
  2. public class SomeActivity extends Activity
  3. {
  4. //....other activity functions
  5. public void showDialog()
  6. {
  7. //construct MyDialogFragment
  8. MyDialogFragment mdf = MyDialogFragment.newInstance(arg1,arg2);
  9. FragmentManager fm = getFragmentManager();
  10. FragmentTransaction ft = fm.beginTransaction();
  11. mdf.show(ft,"my-dialog-tag");
  12. }
  13. //....other activity functions
  14. }

从清单 10-1 中我们可以看出,展示一个 DialogFragment有如下3步:

  1. 创建一个DialogFragment;
  2. 获取对应的 FragmentTransaction;
  3. 通过FragmentTransaction 的show方法展示对话框;

2.2 构建一个FragmentDialog

与其他Fragment一样,推荐使用工厂模式的newInstance()来实现一个DialogFragment。就像Android管理Fragment的生命周期一样,使用默认的空参构造方法,然后使用bundle对象来传入参数。

2.2.1 重写 onCreateView 方法

当你继承一个DialogFragment时,你可以选择重写一个或两个方法来创建对话框。第一个选择是重写onCreateView并在返回一个view;另个一选择是重写onCreateDialog方法并返回一个dialog。 清单 10-2 是一个重写onCreateView的例子

  1. 清单 10-2. Overriding onCreateView() of a DialogFragment
  2. public class MyDialogFragment extends DialogFragment
  3. implements View.OnClickListener
  4. {
  5. .....other functions
  6. public View onCreateView(LayoutInflater inflater,
  7. ViewGroup container, Bundle savedInstanceState)
  8. {
  9. //Create a view by inflating desired layout
  10. View v = inflater.inflate(R.layout.prompt_dialog, container, false);
  11. //you can locate a view and set values
  12. TextView tv = (TextView)v.findViewById(R.id.promptmessage);
  13. tv.setText(this.getPrompt());
  14. //You can set callbacks on buttons
  15. Button dismissBtn = (Button)v.findViewById(R.id.btn_dismiss);
  16. dismissBtn.setOnClickListener(this);
  17. Button saveBtn = (Button)v.findViewById(R.id.btn_save);
  18. saveBtn.setOnClickListener(this);
  19. return v;
  20. }
  21. .....other functions
  22. }

DialogFragment就像一个Fragment一样,将onCreateView中生成的view以对话框形式展示。

2.2.2 重写onCreateDialog

DialogFragment 还可以通过重写onCreateDialog方法来使用,清单10-3 展示了一个例子

  1. Listing 10-3. Overriding onCreateDialog() of a DialogFragment
  2. public class MyDialogFragment extends DialogFragment
  3. implements DialogInterface.OnClickListener
  4. {
  5. .....other functions
  6. @Override
  7. public Dialog onCreateDialog(Bundle icicle)
  8. {
  9. AlertDialog.Builder b = new AlertDialog.Builder(getActivity())
  10. .setTitle("My Dialog Title")
  11. .setPositiveButton("Ok", this)
  12. .setNegativeButton("Cancel", this)
  13. .setMessage(this.getMessage());
  14. return b.create();
  15. }
  16. .....other functions
  17. }

通过重写onCreateDialog,可以简单直接的返回一个对话框,但是远没有重写onCreateView灵活。

2.3 展示一个DialogFragment

当你构造完一个DialogFragment时,需要使用一个FragmentTransaction来展示它。DialogFragment 对象的show()方法接受一个transaction作为参数,用于将该DialogFragment添加到Activity中;然而show()方法并不会修改transaction的返回栈。如果向要添加,需要先将其添加到返回栈在调用show()方法。show方法有如下两种形式:

  1. public int show(FragmentTransaction transaction, String tag)
  2. public int show(FragmentManager manager, String tag)

第一个show() 接受transaction 和tag来展示对话框,返回值为transaction的提交结果;第二个show()方法直接接受一个FragmentManager,该方法是一个简便的show方法,但是使用该方法将不能为transaction添加返回栈。

使用DialogFragment的一个优点是可以通过Fragment的状态管理机制来管理对话框,例如当你在对话框展示的时候旋转屏幕,不需要自己实现状态的管理,可以直接教给Fragment来实现。DialogFragment也提供了界面控制的方法,例如title和样式。

2.4 隐藏一个DialogFragment

隐藏一个DialogFragment的方法有两种,第一种是通过调用DialogFragment对象的dismiss()方法。清单 10-4展示了通过按钮时间调用dismiss()方法。

  1. Listing 10-4. Calling dismiss()
  2. if (someview.getId() == R.id.btn_dismiss)
  3. {
  4. //use some callbacks to advise clients
  5. //of this dialog that it is being dismissed
  6. //and call dismiss
  7. dismiss();
  8. return;
  9. }

DialogFragment 的dismiss()方法将对话框从fragmentManager中移除并且提交这次改变;同时如果该DialogFragment 有返回栈时,dismiss()会自动出栈。调用dismiss()还会调用DialogFragment的销毁回调,包括onDismiss()。

对话框的销毁回调有onCancel()和onDismiss() 两个; 一个Dialog对象有dismiss()和cancel()两个方法可以调用的,而DialogFragment仅保留了dismiss()方法;

在Android官方文档中,Dialog的onCancel()回调是为取消按钮设计的,当用户按返回家或者主动调用cancel时会执行onCancel()回调;而如果用户按了确认按钮(不适用cancel()而使用dismiss()),销毁对话框时只会执行onDismiss();

尽管DialogFragment中不能主动调用cancel(),但是用户按返回键依然会触发onCancel(); 通过onCreateDialog方法可以获取Dialog对象的引用,依旧可以调用cancel;

需要注意的是onDismiss并非与dismiss()一一对应,因为在旋转屏幕时也会隐藏并回调onDismiss。

另一种隐藏对话框的方式为替换。清单 10-5 展示了如何进行DialogFragment的替换;

  1. Listing 10-5. Setting Up a Dialog for a Back Stack
  2. if (someview.getId() == R.id.btn_invoke_another_dialog)
  3. {
  4. Activity act = getActivity();
  5. FragmentManager fm = act.getFragmentManager();
  6. FragmentTransaction ft = fm.beginTransaction();
  7. ft.remove(this);
  8. ft.addToBackStack(null);
  9. //null represents no name for the back stack transaction
  10. HelpDialogFragment hdf =
  11. HelpDialogFragment.newInstance(R.string.helptext);
  12. hdf.show(ft, "HELP");
  13. return;
  14. }

上述代码中,通过fragmenttransaction的remove将当前DialogFragment移除,并且添加了一个新的 HelpDialogFragment,在添加新对象之前,通过ft的addToBackStack方法添加了返回栈。这样当用户按返回键之后又会返回之前的对话框。

Dialog 销毁过程的启示

FragmentManager会管理所有加入其中的Fragment的状态,即当你触发设备配置项(device-configuration)时(例如旋转屏幕),fragment也会跟着重新创建。DialogFragment通过show()和dismiss()方法将自己添加到FragmentManager或从中移除。需要注意的是,show()方法是包含一个添加操作的,而每个Fragment只能被添加一次,因此我们不能先将DialogFragment对象添加到FragmentManager 再执行show()操作。

如果你想要在对话框隐藏之后还保留其状态,你可以在其Activity中保留或者在一个非DialogFragment的Fragment中保留。

3 一个DialogFragment 的案例

本节通过一个实例App演示了DialogFragment的使用,并且使用到了fragment与activity的交互,案例共用到5个java文件:

  • MainActivity.java:应用程序的主Activity。通过简单的Textview展示了帮助文本,并且通过Menu可以启动Dialog。
  • PromptDialogFragment.java:一个DialogFragment的案例。通过layout自定义了view 并且允许用户输入信息。包含3个按钮:保存,取消和帮助。注:在启动帮助对话框时使用技巧将本对话框加入返回栈。
  • AlertDialogFragment.java:一个DialogFragment的案例,通过AlertBuilder直接在Fragment中创建一个Dialog,这是旧的创建对话框的方式。
  • HelpDialogFragment.java:一个展示了帮助信息的非常简单的fragment,该帮助信息可以由主Activity或者PromptDialog启动,在创建时确认具体展示方式。
  • OnDialogDoneListener.java:用Activity 实现,用于从fragment获取消息的接口。 为了使Activity监听fragment,可以在onAttach()方法中使用类型判断,根据当前class是否为OnDialogDoneListener类型来设置监听器,而不需要手动传入参数,代码如下:

    1. try {
    2. OnDialogDoneListener test = (OnDialogDoneListener)act;
    3. }
    4. catch(ClassCastException cce) {
    5. // Here is where we fail gracefully.
    6. Log.e(MainActivity.LOGTAG, "Activity is not listening");
    7. }

3.1 嵌入式对话框的实现

从上述例子中除了弹出对话框的形式,我们还将提示对话框进行了嵌入式显示。将PromptDialogFragment当做一个Fragment嵌入到主Activity 内layout中的FrameLayout中,这样整个PromptDialogFragment的view将按照你预想的方式展示到指定的位置而不再是一个对话框形式。

同时,由于DialogFragment的dismiss方法中执行的操作正是从Fragmentmanager中移除一个Fragment,完美的跟嵌入式的显示方式向结合。

4 一些Google推荐的对话框方案

1、自定义对话可以通过Activity的Dialog样式来实现,只需要在清单文件中将activity的主题设置为Theme.Holo.Dialog即可。

  1. <activity android:theme="@android:style/Theme.Holo.Dialog" >

2、将Activity显示为大屏对话框,而小屏依然为全屏Activity,需要将Activity的主题设置为Theme.Holo.DialogWhenLarge。

  1. <activity android:theme="@android:style/Theme.Holo.DialogWhenLarge" >

5 总结

本章讨论了异步对话框及其在Android中的实现,分为如下部分:

  1. Dialog是什么,我们为什么需要Dialog。
  2. 异步对话框的特性。
  3. 展示一个对话框的三个步骤。
  4. 创建一个Fragment。
  5. DialogFragment中创建一个对话框的两种办法。
  6. FragmentTransaction展示对话框的步骤。
  7. 当对话框展示过程中按返回键后的操作。
  8. 返回栈和管理DialogFragments状态。
  9. 如何接受对话框上按钮点击后的消息。
  10. Fragment和Dialog交互的一个简洁方案。
  11. 一个对话框中再次展示另个对话的实现。
  12. 一些Google推荐的对话框方案。

参考:

Android Doc Dialog

代码:

https://github.com/votzone/DroidCode/tree/master/ProAndroid/DialogFragmentDemo

原文

Android 中Dialog的使用的更多相关文章

  1. Android中Dialog

    在Android中,Dialog是一个非常重要的UI, 它可以方便的给用户提示,用最简洁的方式向用户展示信息, 以下的图片是Dialog的一个整体架构,通过它,可以总体对Dialog有一个很清晰的认识 ...

  2. Android中Dialog的使用

    上一篇博文讲到对话框popWindow的使用,这篇博文主要解说Dialog的使用. 1.什么是Dialog? Dialog就是对话框的一种方式! 在Android开发中.我们常常会须要在Android ...

  3. Android中Dialog对话框的调用及监听

    Android中经常会需要在Android界面上弹出一些对话框提示用户,比如App的退出的时候都会有各种框来挽留你的心,支付宝的时候输入密码的密码框,非常常见及其实用的功能,类似于JS中的alter, ...

  4. Android中Dialog对话框

    布局文件xml: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...

  5. 我的Android进阶之旅------>Android中Dialog系统样式讲解

    今天在维护公司的一个APP的时候,有如下场景. 弹出一个AlertDialog的时候,在系统语言是中文的时候,如下所示: 弹出一个AlertDialog的时候,在系统语言是English的时候,如下所 ...

  6. android从Dialog对话框中取得文本文字

    android中Dialog对话框获取文本文字,只需要使用editor的getText方法就可以获得,示例如下:final EditText et = new EditText(this); et.s ...

  7. Android 自定义Dialog类,并在Activity中实现按钮监听。

      实际开发中,经常会用到Dialog,比如退出时候会弹出是否退出,或者还有一些编辑框也会用Dialog实现,效果图如下: 开发中遇到的问题无非在于如果在Activity中监听这个Dialog中实现的 ...

  8. Android中制作自定义dialog对话框的实例

    http://www.jb51.net/article/83319.htm   这篇文章主要介绍了Android中制作自定义dialog对话框的实例分享,安卓自带的Dialog显然不够用,因而我们要继 ...

  9. 详细解读Android中的搜索框(二)—— Search Dialog

    Search Dialog是提供搜索的控件之一,还有一个是上次小例子给出的searchView,关于SearchView的东西后面会说到.本次先从Search Dialog说起,让大家慢慢理解andr ...

随机推荐

  1. SPOJ2666 QTREE4

    我是萌萌的传送门 我是另一个萌萌的传送门 一道树分治……简直恶心死了……我在调代码的时候只想说:我*************************************************…… ...

  2. canvas image array(canvas图片阵列)

    code:   <!DOCTYPE html> <html> <head>  <title>hehe</title>  </head& ...

  3. 删除SVN版本信息 .svn文件夹

    环境:MyEclipse.Windows 问题描述: 在MyEclipse中当我们需要将一个文件夹(包含若干文件或嵌套文件夹)拷贝到另一个文件夹时,此时文件内容虽然拷贝过去了,但其下面的 .svn文件 ...

  4. hdu 2063 过山车(模板)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2063 过山车 Time Limit: 1000/1000 MS (Java/Others)    Me ...

  5. android query 模糊查询

    package com.example.utils; import java.util.ArrayList; import android.content.ContentValues; import ...

  6. VStudio2015 开发MD风格的windows软件(附上使用第三方库教程)

    MD就是Google的一个安卓5.0+好看界面,都知道win下没有,那么就有大牛弄出了C#版的MD 特别说明:开发环境是.net 4.6 下面开始教程喂! 新建一个工程,这些不要我说了吧,如果没一点基 ...

  7. 十四、css动画基础知识

    引用动画的方式:   1.轻量动画: cubic-bezier(0.165, 0.840, 0.440, 1.000);//加上贝塞尔曲线使动画运动起来更加平滑 2..scrollNews,.m-tr ...

  8. 微信小程序开发踩坑记

    前言 微信小程序自去年公测以来,我司也申请了一个帐号开发,春节前后开始开发,现在终于告一个段落了.谨以此文记录下踩过的坑. 坑1:scroll-view与onPullDownRefresh冲突 由于有 ...

  9. QT的动画效果 抖动 下坠 透明 最近在开发QT收藏了好多链接

    http://blog.csdn.net/liang19890820/article/details/51888114

  10. Maven学习---使用maven进行项目构建

    1. 使用maven进行项目构建 MyEclipse 自带maven 插件 Eclipse 需要单独安装maven插件 1.1. Maven 在企业中怎么用的 ? Maven : 项目构建工具 ,进行 ...