我们尝尝使用 ProgressBar 来向用户展示某个操作的进度,或者提示用户等待,从而提高友好性。
ProgressBar 支持多种风格,通过 style 属性可以为 ProgressBar 指定风格。该属性支持以下几个属性:
其他常用属性:
常用的方法:
Dialog 类是对话框的基类,但您应该避免直接实例化 Dialog,而是使用下列子类之一:
AlertDialog:此对话框可显示标题、最多三个按钮、可选择项列表或自定义布局。
DatePickerDialog 或 TimePickerDialog:此对话框带有允许用户选择日期或时间的预定义 UI。
DatePickerDialog / TimePickerDialog 使用较少,这里就不详细介绍,具体使用可以看这里: Pickers。
重要方法:
对话框的创建需要使用 AlertDialog.Builder 类,通过该类构建一个 AlertDialog.Builder 对象,然后调用该对象的一系列 setXXX 方法,常用的方法有:
更多关于 Dialog 的内容,请看这里: https://developer.android.google.cn/guide/topics/ui/dialogs.html
Notification 是一种全局效果的通知,可以在系统的通知栏中显示。当 APP 向系统发出通知时,它先以图标的形式显示在通知栏中,用户可以通过下拉通知栏查看通知的详情。
Notification 必须包含以下内容:
创建 Notification 主要涉及到 Notification.Builder、Notification 和 NotificationManager:
基本操作:
Notification.Builder builder = new Notification.Builder(this)
.setContentTitle("这是标题")
.setContentText("这是内容")
.setSmallIcon(R.mipmap.ic_launcher);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(1, builder.build());
}
以上是简单的通知应用。
有时候我们需要点击通知,跳转到特定的 Activity 当中,要实现这样的功能,就需要用到之前 Intent 讲到的 pendingIntent,如何设置 PendingIntent 以获得全新任务取决于正在启动的 Activity 的性质。一般有两种情况:
常规 Activity
您要启动的 Activity 是应用的正常工作流的一部分。在这种情况下,请设置 PendingIntent 以启动全新任务并为 PendingIntent提供返回栈,这将重现应用的正常“返回”行为。
特殊 Activity
仅当从通知中启动时,用户才会看到此 Activity。 从某种意义上说,Activity 是通过提供很难显示在通知本身中的信息来扩展通知。对于这种情况,请将 PendingIntent 设置为在全新任务中启动。但是,由于启动的 Activity 不是应用 Activity 流程的一部分,因此无需创建返回栈。点击“返回”仍会将用户带到主屏幕。
常规 Activity
要设置可启动直接进入 Activity 的 PendingIntent,请执行以下步骤:
在清单文件中定义应用的 Activity 层次结构。
添加对 Android 4.0.3 及更低版本的支持。为此,请通过添加 <meta-data>
元素作为 <activity>
的子项来指定正在启动的 Activity 的父项。
对于此元素,请设置 android:name="android.support.PARENT_ACTIVITY"
。 设置 android:value="<parent_activity_name>"
,其中,<parent_activity_name>
是父 <activity>
元素的 android:name
值。请参阅下面的 XML 示例。
同样添加对 Android 4.1 及更高版本的支持。为此,请将 android:parentActivityName
属性添加到正在启动的 Activity 的 <activity>
元素中。
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ResultActivity"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
</activity>
以下代码段演示了该流程:
...
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack
stackBuilder.addParentStack(ResultActivity.class);
// Adds the Intent to the top of the stack
stackBuilder.addNextIntent(resultIntent);
// Gets a PendingIntent containing the entire back stack
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
...
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());
特殊 Activity
下文介绍如何设置特殊 Activity PendingIntent。
特殊 Activity 无需返回栈,因此您不必在清单文件中定义其 Activity 层次结构,也不必调用 addParentStack() 来构建返回栈。取而代之的是,您可使用清单文件设置 Activity 任务选项,并通过调用 getActivity() 创建 PendingIntent:
<activity>
元素FLAG_ACTIVITY_NEW_TASK
标志相结合,这可确保此 Activity 不会进入应用的默认任务。任何具有应用默认关联的现有任务均不受影响。以下代码段显示了该元素:
<activity
android:name=".ResultActivity"
...
android:launchMode="singleTask"
android:taskAffinity=""
android:excludeFromRecents="true">
</activity>
...
FLAG_ACTIVITY_NEW_TASK
和 FLAG_ACTIVITY_CLEAR_TASK
标志调用 setFlags(),将 Activity 设置为在新的空任务中启动。以下代码段演示了该流程:
// Instantiate a Builder object.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
// Creates an Intent for the Activity
Intent notifyIntent =
new Intent(this, ResultActivity.class);
// Sets the Activity to start in a new, empty task
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Creates the PendingIntent
PendingIntent notifyPendingIntent =
PendingIntent.getActivity(
this,
0,
notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
// Puts the PendingIntent into the notification builder
builder.setContentIntent(notifyPendingIntent);
// Notifications are issued by sending them to the
// NotificationManager system service.
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Builds an anonymous Notification object from the builder, and
// passes it to the NotificationManager
mNotificationManager.notify(id, builder.build());
删除通知
除非发生以下情况之一,否则通知仍然可见:
更多关于 Notification 的内容,请看这里:通知
Toast是在窗口表面弹出的一个消息。它只填充消息展现需要的空间,并且用户当前的Activity依然可见和可交互。通知自动的渐入渐出,不接受交互事件。
广播通知能够由Activity或Service创建和显示。如果你创建了一个源自Service的广播通知,它会显示当前有焦点的Activity的前面。
如要需要用户对通知做出响应,请考虑使用状态栏通知。
首先,用makeText()方法实例化一个Toast对象。这个方法需要三个参数:
应用程序的Context对象
要显示的文本消息
通知持续表示的时间
这个方法会返回一个合适的被实例化的Toast对象。你能够用show()方法显示广播通知,显示方法如下:
Context context = getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
这个示例程序给你演示大多数广播通知所需要做的每一件事情。你很少需要再做其他的事情。但是,你可能想要把广播通知放到不同的位置,甚至要使用自己的布局来替代那个简单的文本消息框。以下,将向你介绍如何实现这些想法。
标准的广播通知水平居中显示在屏幕底部附近,你能够通过setGravity(int,int,int)方法来改变这个位置。这个方法有三个参数:
Gravity常量(详细参照Gravity类)
X轴偏移量
Y轴偏移量。
例如,如果你想让通知显示在屏幕的左上角,你可以用下面这样的方法调用:
toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0);
如果你想要向右移动位置,可以增加第二个参数的值。要向下移动,可以增加最后一个参数的值。
如果一个简单的文本消息不同满足现实的需要,你可以给广播通知创建一个定制的布局。要创建一个定制的布局,可以在XML文件或应用程序代码中定义一个View布局,然后把根View对象传递给setView(View)方法。
例如,你可以用下面的XML文件创建一个如下图2所示的广播通知视窗。
<LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android"
android:id="@+id/toast_layout_root"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:background="#DAAA"
>
<ImageView android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="10dp"
/>
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textColor="#FFF"
/>
</LinearLayout>
注意,LinearLayout元素的ID属性值是“toast_layout_root”。你必须使用这个ID的把XML的定义填充到布局中,方法如下:
LayoutInflater inflater = getLayoutInflater();
View layout = inflater.inflate(R.layout.toast_layout,(ViewGroup) findViewById(R.id.toast_layout_root));
ImageView image = (ImageView) layout.findViewById(R.id.image);
image.setImageResource(R.drawable.android);
TextView text = (TextView) layout.findViewById(R.id.text);
text.setText("Hello! This is a custom toast!");
Toast toast = new Toast(getApplicationContext());
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(layout);
toast.show();
首先,用 getLayoutInflater() 方法(或 getSystemService() 方法)获取 LayoutInflater 对象,然后使用 inflate(int, ViewGroup) 方法把 XML 定义填充到布局中,这个方法的第一个参数是布局资源的 ID,第二个参数要填充布局的 View 对象,本例是根 View 对象。你能够使用这个被填充的布局来查找布局中 View 对象,以便获取和定义 ImageView 和 TextView 元素的内容。最后,用 Toast(Context) 方法创建一个广播通知,并设置了一些广播通知的属性,如 Gravity 常量和持续显示时间。然后调用 setView(View) 方法,把它传递给要填充的布局对象。然后调用 show() 方法显示这个定制的广播通知。
注意:除非你要用setView(View)方法定义布局,否则不要使用公共的Toast类构造器。如果不使用定制的布局,必须使用makeText(Context, int, int)方法来创建广播通知。