第6章 对话框

一个对话框是一个小窗口,提示用户做出决定或输入额外的信息,一个对话框不填充屏幕并且通常用于在程序运行时中断,然后弹出通知提示用户,从而直接影响到正在运行的程序。图6-1就是对话框的外观。

图6-1

Dialog类是所有具体对话框的基类,但你应该避免直接实例化Dialog。因为可能有些现成的已经给你提供好了,比如以下几种:

◆AlertDialog

一个对话框,可以显示一个标题(可选),三个按钮(可选),内容的列表(可选),或一个自定义布局。

◆DatePickerDialog或TimePickerDialog

一个对话框,其中有一个预定义的用户界面,允许用户选择一个日期或时间。

◆ProgressDialog

这个我们应该尽量避免使用,它用于显示进度条。但是,如果你如果需要显示这种加载或不确定的进度情况,更好的方法是Activity结合Progress,明确的在布局中使用ProgressBar来更新进度,以让用户明确的看到进度情况。

以上这些类定义了你对话框的风格和结构,但你也可以使用DialogFragment作为你对话框的容器。DialogFragment类提供所有创建和管理外观的控制力,它比直接调用Dialog对象中的方法更好。使用DialogFragment管理对话框可以确保它正确地处理生命周期事件,比如当用户按下后退按钮或旋转屏幕时。这个DialogFragment类还允许您重用对话框的用户界面,就像一个传统的Fragment (比如当你希望对话框在大型和小型屏幕中的UI不一样)。注意DialogFragment类在android3.0或以上版本中才有,如果你需要在低版本中使用它可以使用Support Library,添加这个库到你的应用中。一般比较新的ADT+Eclipse套装会自动把这个库添加到你的项目中。

6.1 创建一个对话框Fragment

你能完成各种各样的对话框设计:包括自定义布局和那些描述。通过DialogFragment创建一个AlertDialog并在onCreateDialog()回调方法中设置一些属性。如代码清单6-1所示:

public class FireMissilesDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// 使用Builder类更方便
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.dialog_fire_missiles)
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//相当于确定
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// 相当于取消
}
});
// 创建AlertDialog对象并返回
return builder.create();
}
}

代码清单6-1

现在当你创建完后调用show()方法,对话框出现图6-2的效果。

图6-2 一个对话框中带有一个消息和两个动作按钮

6.2 构建一个Alert Dialog

AlertDialog类允许您构建各种对话框设计。如图6-3所示, 一个警告对话框有三个区域

图6-3 对话框布局

1. 标题(Title)

这是可选的,如果你需要一个简单的信息或问题的状态,你可以不需要一个标题。

2. 内容区域

它可以显示一条消息,一个列表,或其他自定义布局。

3. 动作按钮

在一个对话框最多不应该超过3个按钮。

AlertDialog.Builder类系统了API允许你创建各种各样的内容,包括布局等,现在在返回看下代码清单6-1可能你会更清晰了。清单中还有两个按钮,如果你看到这样的格式方法如set..Button(),就是设置动作按钮了,下面让我们来看下3种按钮的不同之处:

◆Positive

这个按钮表示接受或着继续,相当于“确定”或者“OK”

◆Negative

这个按钮相当于“取消”

◆Neutral

这是个中立按钮,比如一个“以后提醒我”的功能。

每种按钮只能出现一次,不能同时出现N次。

6.2.1添加一个List

有三种可用的AlertDialog API列表:

一个传统的单选列表

一个持久化的单选列表(单选按钮)

一个持久化的多选列表(复选框)

创建一个单选列表类似于图6-4,你可以使用setItems()方法,如代码清单6-2所示:

图6-4 这个对话框里有标题和列表

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.pick_color);
.setItems(R.array.colors_array, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 'which' 参数包含被选中item的索引位置
}
});
return builder.create();
}

代码清单6-2

因为列表出现在对话框的内容区域里,对话框不能既显示列表又显示一个消息,所以你可以使用setTitle()设置标题以代替消息(message)。为了指定列表中的item,你可以通过数组来调用setItems()方法。或者你能使用setAdapter()来指定一个列表。它允许你使用一个ListAdapter来返回列表和动态数据。如果你选择使用ListAdapter返回一个列表,那么请一直使用Loader以便内容异步加载。关于这方面的内容在“用户界面和布局”和“装载机”章节我们已讲述过。注意:默认情况下,触摸一个list item会dissmiss掉一个对话框,除非你使用下面我们要讲述的持久化选择列表。

6.2.2添加一个持久化的单选或多选列表

为了添加一个列表的多选item或单选item,你可以使用setMultiChoiceItems()或setSingleChoiceItems()方法。例如图6-5是在一个ArrayList中使用多选item的例子。

图6-5 一个多选列表的items

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mSelectedItems = new ArrayList();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.pick_toppings)
.setMultiChoiceItems(R.array.toppings, null,
new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
if (isChecked) {
// 如果选择一个item,就添加一个索引
mSelectedItems.add(which);
} else if (mSelectedItems.contains(which)) {
// 否则,如果item已经存在就移除它
mSelectedItems.remove(Integer.valueOf(which));
}
}
})
// 设置动作按钮
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
// 用户点击OK,保存已选中的item结果到某处或者返回结果到已打开的对话框中
...
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
...
}
}); return builder.create();
}

代码清单6-3

虽然一个传统的列表和一个单选列表都提供一个“单选”动作。但如果你想要保存用户的选择,你应该使用setSingleChoiceItems()。就是说如果你稍后再次打开对话框应该表明用户当前的选择是什么,然后你使用单选按钮创建一个列表。

6.2.3创建以自定义的布局

如果你想要一个自定义的布局,那么你可以使用AlertDialog.Builder对象中的setView()方法来添加一个你创建的布局。默认情况下,自定义布局会填充对话框窗口,但你仍然能使用AlertDialog.Builder中的方法来添加动作按钮和标题。例如,图6-6和代码清单6-4所示:

图6-6 一个自定义的对话框布局

代码文件在res/layout/dialog_signin.xml中

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:src="@drawable/header_logo"
android:layout_width="match_parent"
android:layout_height="64dp"
android:scaleType="center"
android:background="#FFFFBB33"
android:contentDescription="@string/app_name" />
<EditText
android:id="@+id/username"
android:inputType="textEmailAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="4dp"
android:hint="@string/username" />
<EditText
android:id="@+id/password"
android:inputType="textPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="16dp"
android:fontFamily="sans-serif"
android:hint="@string/password"/>
</LinearLayout>

代码清单6-4

注意:默认情况下,当你设置一个EditText元素为“textPassword”输入类型时,字体会设置为等宽字体,因此你应该使用字体为“sans-serif”来统一匹配文本字体风格。为了在DialogFragment 中inflate布局,你可以使用getLayoutInflater()获得一个LayoutInflater并调用inflate(),然后setView()。如代码清单6-5所示:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// 获得layout inflater
LayoutInflater inflater = getActivity().getLayoutInflater(); builder.setView(inflater.inflate(R.layout.dialog_signin, null))
//设置action响应
.setPositiveButton(R.string.signin, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
// todo...
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
LoginDialogFragment.this.getDialog().cancel();
}
});
return builder.create();
}

代码清单6-5

注意:如果你想要自定义对话框,你其实可以使用Activity来作为对话框。简单的创建一个activity然后在manifest中的<activity>节点下设置它的主题(theme)为Theme.Holo.Dialog即可。如代码清单6-6所示:

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

代码清单6-6

就是这样。这个activity现在作为一个对话框窗口显示而不是全屏显示。

6.3 通过事件返回到对话框的Host

当用户触摸一个对话框的动作按钮或选择一个item时,你的DialogFragment可能执行必要的操作,但常常你想要传递这个事件到已经打开的对话框中的上层activity或fragment中。为了做到这些,定义一个点击事件的接口类型。然后实现接口中的方法。如代码清单6-7所示:

public class NoticeDialogFragment extends DialogFragment {
public interface NoticeDialogListener {
public void onDialogPositiveClick(DialogFragment dialog);
public void onDialogNegativeClick(DialogFragment dialog);
} NoticeDialogListener mListener; @Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (NoticeDialogListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement NoticeDialogListener");
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Build the dialog and set up the button click handlers
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.dialog_fire_missiles)
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// 发送positive按钮事件回调到host activity
mListener.onDialogPositiveClick(NoticeDialogFragment.this);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// 发送negative按钮事件回调到host activity
mListener.onDialogPositiveClick(NoticeDialogFragment.this);
}
});
return builder.create();
} }

代码清单6-7

代码清单6-7只是定义接口,当然我们还需要实现这个接口,下面代码清单6-8就是如何实现并运用的:

public class MainActivity extends FragmentActivity
implements NoticeDialogFragment.NoticeDialogListener{
... public void showNoticeDialog() {
DialogFragment dialog = new NoticeDialogFragment();
dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
} @Override
public void onDialogPositiveClick(DialogFragment dialog) {
} @Override
public void onDialogNegativeClick(DialogFragment dialog) {
}
}

代码清单6-8

6.4 显示一个对话框

当你想要显示你的对话框时,创建一个DialogFragment的实例并调用show()方法,并传递一个FragmentManager和一个标签名字。你可以通过getSupportFragmentManager()来获得一个FragmentManager。如代码清单6-9所示:

public void confirmFireMissiles() {
DialogFragment newFragment = new FireMissilesDialogFragment();
newFragment.show(getSupportFragmentManager(), "missiles");
}

代码清单6-9

第二个参数,"missiles"是一个唯一的标签名,因为某些必要情况下系统用来保存和恢复fragment的状态。当然你可以通过findFragmentByTag()来获得一个fragment。

6.5 显示一个全屏对话框或作为一个嵌入式

你可能有一个UI设计,你想要一个区域用来放置这个UI,这里你用到了一个对话框,但有时候你又需要全屏显示(比如在大屏幕下可能作为标准的对话框,在小屏幕下你可能需要全屏)。DialogFragment类提供了这种灵活性。但是,你不能使用AlertDialog.Builder或其他Dialog对象来处理这种情况。如果你想要DialogFragment是可嵌入的,你必须在布局中定义对话框的UI,然后在onCreateView()回调方法中载入布局。如代码清单6-10所示(purchase_items.xml):

public class CustomDialogFragment extends DialogFragment {

    @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.purchase_items, container, false);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
return dialog;
}
}

代码清单6-10

下面是一些代码,根据屏幕大小决定是否显示Fragment作为一个对话框或全屏UI,如代码清单6-11所示:

public void showDialog() {
FragmentManager fragmentManager = getSupportFragmentManager();
CustomDialogFragment newFragment = new CustomDialogFragment(); if (mIsLargeLayout) {
// 如果是大型布局,作为对话框显示即可
newFragment.show(fragmentManager, "dialog");
} else {
// 如果是小设备,作为fragment全屏显示
FragmentTransaction transaction = fragmentManager.beginTransaction();
//指定一个过渡动画
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
// 使用全屏就把对话框newFragment作为根view
transaction.add(android.R.id.content, newFragment)
.addToBackStack(null).commit();
}
}

代码清单6-11

在这个例子中,mIsLargeLayout这个boolean值是我们代码检测出来的结果,其实更好的方法是在不同的文件夹下指定资源值,如下所示:

res/values/bools.xml

<!—默认boolean值 -->
<resources>
<bool name="large_layout">false</bool>
</resources>

res/values-large/bools.xml

<!—Large屏幕下的boolean值-->
<resources>
<bool name="large_layout">true</bool>
</resources>

然后再代码中这样获取如代码清单6-12所示:

boolean mIsLargeLayout;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mIsLargeLayout = getResources().getBoolean(R.bool.large_layout);
}

代码清单6-12

6.5.1 在大屏幕下显示一个以对话框形式的activity

有个很简单的方法就是,如代码清单6-13所示:

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

代码清单6-13

6.6 Dissmiss对话框

当用户触摸任何一个由AlertDialog.Builder创建动作按钮时,系统会dismiss掉对话框。当用户触摸一个对话框的itme时系统会dismiss对话框,除单选按钮或复选框之外。当然你也能手动调用DialogFragment的dismiss()的方法。如果你需要当对话框消失时,执行某些操作,你可以在DialogFragment中实现onDismiss()方法。当然有些时候你想取消一个对话框。如果用户按下返回按钮,触摸对话框外面区域或调用Dialog的cancel()方法都会执行取消操作,或者你可以在DialogFragment中实现onCancel()方法来做一些取消之前的操作。注意:系统会优先调用onDismiss()。如果你主动调用了Dialog.dismiss()或者DialogFragment.dismiss()那么系统会调用onDismiss()而不会调用onCancel()。所以通常情况下我们都使用dismiss()来关闭对话框。

本文来自jy02432443,是本人辛辛苦苦一个个字码出来的,转载请保留出处,并保留追究法律责任的权利 QQ78117253 

第三部分:Android 应用程序接口指南---第二节:UI---第六章 对话框的更多相关文章

  1. 第三部分:Android 应用程序接口指南---第二节:UI---第一章 用户界面和布局

    第1章 用户界面和布局 应用程序的用户界面就是用户能看到并可以与它交互的任何东西.Android提供多种预置的UI组件,如结构化布局对象和允许你为应用程序创建图形用户界面的UI控件.Android也会 ...

  2. 第三部分:Android 应用程序接口指南---第二节:UI---第五章 设置(Settings)

    第5章 设置(Settings) 应用程序通常包括允许用户修改应用程序的特性和行为的设置功能.例如,一些应用程序允许用户指定通知是否启用或指定多久使用云同步数据.如果你想要为你的应用程序提供设置,你应 ...

  3. 第三部分:Android 应用程序接口指南---第二节:UI---第二章 输入控件

    第2章 输入控件 输入控件是应用程序中用户接口的一种交互式组件.Android提供了大量的可供人们在UI中使用的控件,比如按钮.文本区域.(带滑块的)进度条.复选框.缩放按钮以及切换按钮等等. 在UI ...

  4. 第三部分:Android 应用程序接口指南---第二节:UI---第四章 Action Bar

    第4章 Action Bar Action Bar是一个能用于确定应用程序和用户的位置,并提供给用户操作和导航模式的窗口功能.如果需要显著地展示当前用户的操作或导航,应该使用Action Bar,因为 ...

  5. 第三部分:Android 应用程序接口指南---第二节:UI---第九章 搜索

    第9章 搜索 在android平台上搜索是一个核心的用户功能.无论内容位于设备或网络上,用户应该能够搜索任何对它们可用的数据.为了创建一个一致的用户搜索体验,Android平台提供了一个搜索框架帮助你 ...

  6. 第三部分:Android 应用程序接口指南---第二节:UI---第七章 通知

    第7章 通知 一个通知是一条消息他是显示于你应用程序之外的一个界面中.当你告诉系统要发布一个通知时,它首先作为一个icon出现在通知区域.为了看见通知的细节,用户可以点击通知区域展开一个新的界面.下面 ...

  7. 第三部分:Android 应用程序接口指南---第二节:UI---第十一章 样式和主题

    第11章 样式和主题 style是用于指定View或window的外观和格式的一系列属性的集合.style可以指定高(height).填补(padding).字体颜色.字体大小.背景颜色等等属性.st ...

  8. 第三部分:Android 应用程序接口指南---第二节:UI---第三章 菜单

    第3章 菜单 在许多不同类型的应用中,菜单通常是一种用户界面组件.为了提供给用户提供熟悉且一致的体验,你需要使用菜单API来展示用户动作和你Activity中的其他选项. 从安卓3.0系统(API l ...

  9. 第三部分:Android 应用程序接口指南---第二节:UI---第八章 Toast通知

    第8章 Toast通知 Toast通知是在窗口前面弹出的信息.它只占有信息所需要的空间量,并且用户当前的activity仍然是可见的.可互动的.这种通知自动地淡入和淡出,它不接受交互事件.他相当于一种 ...

随机推荐

  1. StringBuilder和+来串接字符串,时间的比较

    一:程序比较 1.使用+ 2.使用的时间 虽然时间一直在变动,但是仍然可以看到时间在1000ms左右 3.使用StringBuilder 4.使用的时间 虽然时间每次在变化,但是时间在350ms左右变 ...

  2. Codeblocks 常用快捷键

    编辑部分: Ctrl + A:全选Ctrl + C:复制Ctrl + X: 剪切Ctrl + V:粘贴Ctrl + Z:撤销Ctrl + S:保存Ctrl + Y / Ctrl + Shift + Z ...

  3. laravel5 项目上线后务必将开发环境更改为生产环境

    如果以开发环境上线,出错信息将全通过json暴露出来了,屏蔽方式如下: .env 文件设置如下APP_ENV=productionAPP_DEBUG=false 改完设置后把缓存清理一遍 如果更改后清 ...

  4. 洛谷 P1057 传球游戏 【dp】(经典)

    题目链接:https://www.luogu.org/problemnew/show/P1057 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游 ...

  5. HBase 开发环境搭建(Eclipse\MyEclipse + Maven)

    写在前面的话 首先, 搭建基于MyEclipse的Hadoop开发环境 相信,能看此博客的朋友,想必是有一定基础的了.我前期写了大量的基础性博文.可以去补下基础. 比如, CentOS图形界面下如何安 ...

  6. JS中获取文件点之后的后缀字符

    var FileName = $("#file").val(); var index1=FileName.lastIndexOf("."); var index ...

  7. python新手总结(二)

    random模块 随机小数 random uniform 随机整数 randint randrange 随机抽取 choice sample 打乱顺序 shuffle random.random() ...

  8. C# 设置MDI子窗体只能弹出一个的方法

    Windows程序设计中的MDI(Multiple Document Interface)官方解释就是所谓的多文档界面,与此对应就有单文档界面 (SDI), 它是微软公司从Windows .0下的Mi ...

  9. 获取运行端口监听的用户身份auth-owner

    获取运行端口监听的用户身份auth-owner   Windows系统提供工作在TCP 113端口的授权服务(Authentication Service),用来判断TCP连接的用户.Nmap的aut ...

  10. 在java中构建json对象,返回给前端页面

    // 给客户端返回一个json对象 StringBuilder sb = new StringBuilder("{"); sb.append("\"name\& ...