Android学习之Notifications(超详细)

当后台服务需要提示用户来响应某个事件时,应该使用状态栏通知。后台服务不应该自己去启动一个activity来与用户互动,它应该创建一个状态栏通知,当用户选择这个通知去启动activity

创建一个普通的通知栏

  NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
Notification notification = builder
        .setSmallIcon(R.drawable.tubiao)                                                .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.fengmian,null))                                        .setWhen(System.currentTimeMillis())
.setContentTitle("this is title")
.setContentText("this is content")
 .build();
   manager.notify(1,notification);

效果:
Android学习之Notifications(超详细)_第1张图片
这是一个最普通的通知栏,一般都会为通知添加至少一个动作(Action),这个动作可以是跳转到Activity、启动一个Service或发送一个Broadcas等。 通过以下方式为通知添加动作:
使用PendingIntent
通过大视图通知的 Action Button //仅支持Android 4.1 (API level 16)及更高版本

NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
   NotificationCompat.Builder builder = new NotificationCompat.Builder(this); 
Intent intent = new Intent(this,geciActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,1,intent,0);
Notification notification = builder.setSmallIcon(R.drawable.tubiao)                                          .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.fengmian,null))                                         .setWhen(System.currentTimeMillis())
.setContentTitle("this is title")
.setContentText("this is content")                                          .setContentIntent(pendingIntent)
.build();
manager.notify(1,notification);

更新通知

更新通知很简单,只需再次发送相同ID的通知即可,如果之前的通知依然存在则会更新通知属性,如果之前通知不存在则重新创建。

Notification notification2 =
                 builder.setSmallIcon(R.drawable.tubiao)
 .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.fengmian,null))
                .setWhen(System.currentTimeMillis())
                .setContentTitle("this is title22222")
                .setContentText("this is content222222")
                .setContentIntent(pendingIntent)
                .build();
        manager.notify(1,notification2);

效果:
Android学习之Notifications(超详细)_第2张图片

取消通知:

取消通知有如下4种方式:
1. 点击通知栏的清除按钮,会清除所有可清除的通知0
2. 设置了 setAutoCancel() 或 FLAG_AUTO_CANCEL的通知,点击该通知时会清除它
3. 通过 NotificationManager 调用 cancel() 方法清除指定ID的通知
4. 通过 NotificationManager 调用 cancelAll() 方法清除所有该应用之前发送的通知

大视图通知:

通知有两个类型,一种是普通视图,一种是大视图:
普通视图:
这里写图片描述
大视图:
这里写图片描述

默认情况下是普通视图,可以通过NotificationCompat.Bulider.setStyle()设置大视图
例子:

Notification notification3 =
 builder.setSmallIcon(R.drawable.tubiao)
 .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.fengmian,null))
.setContentTitle("this is title2222233333")
 .setContentText("this is content22222233333")
 .setContentIntent(pendingIntent)
 .setStyle(new NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(),R.drawable.fengmian,null)))
.setStyle(new NotificationCompat.BigTextStyle().bigText("ddsfsdvdvddadaergadvadfaasdferavadgarvaergadvaergvasgqrefaerhtrrthbsdbsrtgadgw"))                       .addAction(R.drawable.zuo,null,pendingIntent)                       .addAction(R.drawable.you,null,pendingIntent)
.build();
manager.notify(1,notification3);

效果:
Android学习之Notifications(超详细)_第3张图片

这个大视图是通过双手上下平移展开的。

进度条通知

  • 明确进度的进度条
    使用setProgress(max, progress, false)来更新进度。
    max: 最大进度值
    progress: 当前进度
    false: 是否是不明确的进度条
    模拟下载过程:
int id = 1;
...
mNotifyManager = (NotificationManager) 
    getSystemService(Context.NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle("Picture Download")
    .setContentText("Download in progress")
    .setSmallIcon(R.drawable.ic_notification);

// Start a lengthy operation in a background thread
new Thread(
    new Runnable() {
        @Override
        public void run() {
            int incr;
            for (incr = 0; incr <= 100; incr+=5) {
                mBuilder.setProgress(100, incr, false);
                mNotifyManager.notify(id, mBuilder.build());
                try {
                    // Sleep for 5 seconds
                    Thread.sleep(5*1000);
                } catch (InterruptedException e) {
                    Log.d(TAG, "sleep failure");
                }
            }
            mBuilder.setContentText("Download complete")//下载完成           
                    .setProgress(0,0,false);    //移除进度条
            mNotifyManager.notify(id, mBuilder.build());
        }
    }
).start();

这里写图片描述

  • 不明确进度的进度条:
    使用setProgress(0, 0, true)来表示进度不明确的进度条
    mBuilder.setProgress(0, 0, true); mNotifyManager.notify(id, mBuilder.build());
    这里写图片描述

自定义通知

Android系统允许使用RemoteViews来自定义通知。
自定义普通视图通知高度限制为64dp,大视图通知高度限制为256dp。同时,建议自定义通知尽量简单,以提高兼容性。
自定义通知需要做如下操作:
1、创建自定义通知布局
2、使用RemoteViews定义通知组件,如图标、文字等
3、调用setContent()将RemoteViews对象绑定到NotificationCompat.Builder
4、同正常发送通知流程
注意: 避免为通知设置背景,因为兼容性原因,有些文字可能看不清。

RemoteViews contentView = new RemoteViews(getPackageName(),R.layout.notification);
        contentView.setTextViewText(R.id.tubiao_title,title);
        contentView.setTextViewText(R.id.tubiao_artist,artist);
        if(bitmap !=null){
            Log.d("bitmap","aaaaaa");
            contentView.setImageViewBitmap(R.id.tubiao_bitmap,bitmap);
        }else {
            contentView.setImageViewResource(R.id.tubiao_bitmap,R.drawable.fengmian);
        }
builder.setSmallIcon(R.drawable.tubiao)
                .setWhen(System.currentTimeMillis())
                .setOngoing(true)
                .setContentIntent(pendingIntent)
                .setContent(contentView);

        notification  = builder.build();

        notification.flags  = Notification.FLAG_NO_CLEAR;
        notification.priority = Notification.PRIORITY_DEFAULT;

布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="200dp">

    <ImageView
        android:layout_width="100dp"
        android:layout_height="match_parent"
        android:id="@+id/tubiao_bitmap"
        android:layout_alignParentLeft="true"
        android:layout_marginRight="10dp"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tubiao_title"
        android:layout_toEndOf="@id/tubiao_bitmap"
        android:textSize="18sp"
        android:text="qqqqqq"
        android:textStyle="bold"
        />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tubiao_artist"
        android:text="aaaa"
        android:layout_marginRight="20dp"
        android:textSize="12sp"
        android:layout_toEndOf="@id/tubiao_title"
        />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:id="@+id/relative"
        android:layout_toEndOf="@id/tubiao_bitmap"
        android:layout_below="@id/tubiao_title"
        >
        <ImageButton
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:src="@drawable/zuo1"
            android:layout_margin="10dp"
            android:layout_centerVertical="true"
            android:id="@+id/tubiao_zuo"
            />
        <ImageButton
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:src="@drawable/zanting1"
            android:layout_margin="10dp"
            android:id="@+id/tubiao_zanting"
            android:layout_centerVertical="true"
            android:layout_centerHorizontal="true"
            />
        <ImageButton
            android:layout_width="20dp"
            android:layout_height="20dp"
            android:src="@drawable/you1"
            android:layout_margin="10dp"
            android:id="@+id/tubiao_you"
            android:layout_centerVertical="true"
            android:layout_alignParentEnd="true"
            />

    RelativeLayout>

RelativeLayout>

效果:
Android学习之Notifications(超详细)_第4张图片

定义通知文本样式
android:style/TextAppearance.Material.Notification.Title // 通知标题样式
android:style/TextAppearance.Material.Notification // 通知内容样式

通知的标准样式和布局
notification_template_material_base.xml
notification_template_material_big_base.xml
notification_template_material_big_picture.xml
notification_template_part_chronometer.xml
notification_template_progressbar.xml
等等

保留Activity返回栈
有两种常用的状态栏通知,其中之一是日历发出的事件提醒通知,还有一种是收到邮箱时邮箱发出的通知。他们代表两种处理状态栏通知的典型模式:启动一个不属于主程序的activity,或者启动一整个应用实例来代表通知的各个状态点。

下面描述两种模式下activity返回栈是如何工作的
日历的通知:
1. 用户正在日历里新建一个事件,它想到需要的邮箱中复制一段信息
2. 用户选择主界面>邮箱
3. 在邮箱界面时,日历弹出了一个新的会议通知。
4. 用户点击通知,会跳转到日历中的activity,显示这次会议的具体信息。
5. 用户看完会议信息,按下返回键,将会回到邮箱界面,也是当时收到通知后离开的那个界面

邮件通知:
1. 用户正在写一封邮件,此时需要去日历中查看日期
2. 主界面>日历
3. 当在日历中时,收到一个新邮箱通知
4. 用户选择这个通知,这个界面会代替了之前写邮件的界面,但是之前写的内容会存到草稿中
5. 用户点击一次返回,返回到邮箱列表中(邮箱的典型流程),再按一次返回键就会回到日历中去。

在一个类似邮箱通知中,通知启动的界面会代表该通知状态中的主程序。例如,当点击邮件通知启动邮件界面,根据收到的邮件数量要么显示邮件列表,要么显示一个邮件详情。为了实现这个的行为,我们将启动新的activity栈来表示通知的不管应用程序的状态是什么。

下面的代码展示如何实现这样的通知。最重要的方法是 makeMessageIntentStack(),它构造了代表新的acticity栈中的 intents.(如果使用fragments,你会需要初始化你的 fragment和应用状态,以便当用户点击返回时,会返回到fragment的上一个状态) 这个方法的核心代码是 Intent.makeRestartActivityTask() 方法,它会使用合适的标志创建 activity 栈中的根 activity,比如 Intent.FLAG_ACTIVITY_CLEAR_TASK.

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        showAppNotifiction();

    }

    void showAppNotifiction(){
        NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        CharSequence form = "Joe";
        CharSequence message;
        switch ((new Random().nextInt())%3){
            case 0: message = " r u hungry?";
                break;
            case 1:message = "im nearby y";
                break;
            default:
                message = "meet y for dinner";
                break;
        }

        PendingIntent content = PendingIntent.getActivities(this,0,
                makeMessageIntentStack(this,form,message),PendingIntent.FLAG_CANCEL_CURRENT);

        Notification notification = builder
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentText("ddddddd")
                .setTicker(message)
                .setWhen(System.currentTimeMillis())
                .setContentIntent(content)
                .build();
        manager.notify(1,notification);


    }


    static Intent[] makeMessageIntentStack(Context context,CharSequence from,CharSequence msg){
        Intent[] intents = new Intent[4];

    // First: root activity of root
    // This is a convenient way to make the proper Intent to launch and
    // reset an application's task.
        intents[0] = Intent.makeRestartActivityTask(new ComponentName(context,root.class));

        intents[1] = new Intent(context,root1.class);
        intents[1].putExtra("Path","App");

        intents[2] = new Intent(context,root2.class);
        intents[2].putExtra("Path","App/Notifiction");

        intents[3] = new Intent(context,message.class);
        intents[3].putExtra("form",from);
        intents[3].putExtra("msg",msg);
        return intents;
    }
}

这个的结果,在打开app的时候,是mian界面,当点击notification后,出现message界面,点击三次返回root2->root2->root,再点一次返回,退出程序。

在一个日历的通知中,通知启动的界面通常不属于应用程序的进程。比如当用户收到日历的通知时,选择这个通知将会启动一个特殊界面来显示代办事项—这个界面仅能从通知中启动,无法通过日历导航过去.
下面的代码发送了一条这样的通知,与上面的通知相似,但是 PendingIntent 只能展示一个activity,也就是专门用来显示代办事项的activity.

void showInterstitialNotification() {
    // look up the notification manager service
    NotificationManager nm = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);

    // The details of our fake message
    CharSequence from = "Dianne";
    CharSequence message;
    switch ((new Random().nextInt()) % 3) {
        case 0: message = "i am ready for some dinner"; break;
        case 1: message = "how about thai down the block?"; break;
        default: message = "meet u soon. dont b late!"; break;
    }

    // The PendingIntent to launch our activity if the user selects this
    // notification.  Note the use of FLAG_CANCEL_CURRENT so that, if there
    // is already an active matching pending intent, cancel it and replace
    // it with the new Intent.
    Intent intent = new Intent(this, message.class);
    intent.putExtra(“form”, from);
    intent.putExtra(“message”, message);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
            intent, PendingIntent.FLAG_CANCEL_CURRENT);

    // The ticker text, this uses a formatted string so our message could be localized
    String tickerText = getString(R.string.imcoming_message_ticker_text, message);

    // construct the Notification object.
    //这个方面现在不行倡议使用
    Notification notif = new Notification(R.drawable.stat_sample, tickerText,
            System.currentTimeMillis());

    // Set the info for the views that show in the notification panel.
    notif.setLatestEventInfo(this, from, message, contentIntent);

    notif.defaults = Notification.DEFAULT_ALL;

    // Note that we use R.layout.incoming_message_panel as the ID for
    // the notification.  It could be any integer you want, but we use
    // the convention of using a resource id for a string related to
    // the notification.  It will always be a unique number within your
    // application.
    nm.notify(R.string.imcoming_message_ticker_text, notif);

然而这样还不够,因为android默认所有的组件都跑在一个进程当中,所有这样简单启动一个 activity可能会将这个 activity 加入到你的应用的返回栈中。想要正确的实现这样的通知,需要在 manifest 文件中给 activity 添加这些属性:android:launchMode=”singleTask”, android:taskAffinity=”” 和 android:excludeFromRecents=”true”.完整的描述如下:

<activity android:name=".app.IncomingMessageInterstitial"
        android:label="You have messages"
        android:theme="@style/ThemeHoloDialog"
        android:launchMode="singleTask"
        android:taskAffinity=""
        android:excludeFromRecents="true">
activity>

当你从这个 activity 当中启动其他 activity时要十分小心,因为它不是应用一部分,也不会显示在最近的应用中,当有新的数据需要显示时必须要重新启动这个 activity. 最好的办法是从这个activity中启动的其他activity都要加载在它们自己的栈中。这样做的时候要多留意这个新的栈与之前离开的栈的互动。这同前面提到的邮件类型的通知很相似,使用前面代码中的 makeMessageIntentStack() 方法,完成类似下面的点击事件:

void switchToApp() {
    // We will launch the app showing what the user picked.  In this simple
    // example, it is just what the notification gave us.
    CharSequence from = getIntent().getCharSequenceExtra("from");
    CharSequence msg = getIntent().getCharSequenceExtra("form);
    // Build the new activity stack, launch it, and finish this UI.
    Intent[] stack = message.makeMessageIntentStack(this, from, msg);
    startActivities(stack);
    finish();
}

在main中先用showInterstitialNotification() ,再用switchToApp(),直接出现message的界面。之后和前面一样

默认情况下,从通知启动一个Activity,按返回键会回到主屏幕。但某些时候有按返回键仍然留在当前应用的需求,这就要用到TaskStackBuilder了。
1、在manifest中定义Activity的关系
Android 4.0.3 及更早版本

<activity
    android:name=".ResultActivity">
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value=".MainActivity"/>
activity>
Android 4.1 及更高版本
<activity
    android:name=".ResultActivity"
    android:parentActivityName=".MainActivity">
activity>

2、创建返回栈PendingIntent
Intent resultIntent = new Intent(this, ResultActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// 添加返回栈
stackBuilder.addParentStack(ResultActivity.class);
// 添加Intent到栈顶
stackBuilder.addNextIntent(resultIntent);
// 创建包含返回栈的pendingIntent
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());
上述操作后,从通知启动ResultActivity,按返回键会回到MainActivity,而不是主屏幕。

特殊Activity
默认情况下,从通知启动的Activity会在近期任务列表里出现。如果不需要在近期任务里显示,则需要做以下操作:
1、在manifest中定义Activity

<activity
    android:name=".ResultActivity"
    android:launchMode="singleTask"
    android:taskAffinity=""
    android:excludeFromRecents="true">
activity>

2、构建PendingIntent
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
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);

PendingIntent notifyPendingIntent =
PendingIntent.getActivity(this, 0, notifyIntent,
PendingIntent.FLAG_UPDATE_CURRENT);

builder.setContentIntent(notifyPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(id, builder.build());
上述操作后,从通知启动ResultActivity,此Activity不会出现在近期任务列表中。

通知常见属性和常量
通知的提醒方式


1、声音提醒
默认声音
notification.defaults |= Notification.DEFAULT_SOUND;
自定义声音
notification.sound = Uri.parse(“file:///sdcard0/notification.ogg”);
2、震动提醒
默认振动
notification.defaults |= Notification.DEFAULT_VIBRATE;
自定义振动
long[] vibrate = {100, 200, 300, 400}; //震动效果
// 表示在100、200、300、400这些时间点交替启动和关闭震动 notification.vibrate = vibrate;
3、闪烁提醒
默认闪烁
notification.defaults |= Notification.DEFAULT_LIGHTS;
自定义闪烁
notification.ledARGB = 0xff00ff00; // LED灯的颜色,绿灯
notification.ledOnMS = 300; // LED灯显示的毫秒数,300毫秒
notification.ledOffMS = 1000; // LED灯关闭的毫秒数,1000毫秒
notification.flags |= Notification.FLAG_SHOW_LIGHTS; // 必须加上这个标志
常见的Flags
FLAG_AUTO_CANCEL
当通知被用户点击之后会自动被清除(cancel)
FLAG_INSISTENT
在用户响应之前会一直重复提醒音
FLAG_ONGOING_EVENT
表示正在运行的事件
FLAG_NO_CLEAR
通知栏点击“清除”按钮时,该通知将不会被清除
FLAG_FOREGROUND_SERVICE
表示当前服务是前台服务
更多Notification属性详见Notification。


基本属性

publicBuilder
setTicker(CharSequence tickerText)

设置状态栏开始动画的文字

publicBuilder
setContentTitle(CharSequence title)

设置内容区的标题,必须设置

publicBuilder
setContentText(CharSequence text)

设置内容区的内容,必须设置

publicBuilder
setContentIntent(PendingIntent intent)

设置点击通知后操作(可以跳转Activity,打开Service,或者发送广播)

publicBuilder
setColor(@ColorIntint
argb)

这个可以设置smallIcon的背景色

publicBuilder
setSmallIcon(@DrawableResint
icon)

设置小图标,必须设置

publicBuilder
setLargeIcon(Bitmap b)

设置打开通知栏后的大图标

publicBuilder
setWhen(long when)

设置显示通知的时间,不设置默认获取系统时间,这个值会在Notification上面显示出来

publicBuilder
setAutoCancel(boolean autoCancel)

设置为true,点击该条通知会自动删除,false时只能通过滑动来删除

publicBuilder
setPriority(int pri)

设置优先级,级别高的排在前面

publicBuilder
setDefaults(int defaults)

设置上述铃声,振动,闪烁用|分隔,常量在Notification里

publicBuilder
setOngoing(boolean ongoing)

设置是否为一个正在进行中的通知,这一类型的通知将无法删除

通知的提醒方式

声音提醒

默认声音

notification.defaults|=Notification.DEFAULT_SOUND;

自定义声音

notification.sound=Uri.parse(“file:///sdcard0/notification.ogg”);

震动提醒

默认振动

notification.defaults|=Notification.DEFAULT_VIBRATE;

自定义振动

long[]
vibrate ={100,200,300,400};//震动效果,表示在100、200、300、400这些时间点交替启动和关闭震动

notification.vibrate=
vibrate;

闪烁提醒

默认闪烁

notification.defaults|=Notification.DEFAULT_LIGHTS;

自定义闪烁

notification.ledARGB=0xff00ff00;//
LED灯的颜色,绿灯

notification.ledOnMS=300;//
LED灯显示的毫秒数,300毫秒

notification.ledOffMS=1000;//
LED灯关闭的毫秒数,1000毫秒

notification.flags|=Notification.FLAG_SHOW_LIGHTS;//
必须加上这个标志

PendingIntent

PendingIntent pendingIntent=PendingIntent.getActivity(MainActivity.this,(int)SystemClock.uptimeMillis(),newIntent(MainActivity.this,OpenActivity.class),PendingIntent.FLAG_UPDATE_CURRENT);

flags有四种不同的值:

FLAG_CANCEL_CURRENT:如果构建的PendingIntent已经存在,则取消前一个,重新构建一个。

FLAG_NO_CREATE:如果前一个PendingIntent已经不存在了,将不再构建它。

FLAG_ONE_SHOT:表明这里构建的PendingIntent只能使用一次。

FLAG_UPDATE_CURRENT:如果构建的PendingIntent已经存在,那么系统将不会重复创建,只是把之前不同的传值替换掉。通常做法就是在构建PendingIntent的时候传入不一样的requestCode来更新PendingIntent

Toast Notification

首先,用makeText()方法实例化一个Toast对象。该方法需要三个参数:当前应用的Context,文本消息,和toast的持续时间。该方法返回一个实例化过的Toast对象。你可以用show()方法将该toast通知显示出来,见下例:

Context context = getApplicationContext();
CharSequence text = "Hello toast!"
intduration = Toast.LENGTH_SHORT;

Toast toast = Toast.makeText(context, text, duration);
toast.show();

定位你的toast
一个标准toast通知垂直剧中出现在靠近屏幕底部的位置。你可以通过setGravity(int, int, int)方法来改变其位置。三个参数分别是:一个Gravity常量,一个x方向的偏移值和一个y方向的偏移值。

例如,如果你决定让toast出现在左上角,你可以这样设置:

toast.setGravity(Gravity.TOP | Gravity.LEFT, 0, 0);

如果你想要向右移动,增加第二个参数的值;增加第三个参数的值向下移动。

自定义的Toast视图
首先定义toast的布局:

<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:layout_textColor="#FFF"/>
LinearLayout>

然后展开布局:

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();

浮动通知

Android 5.0(API level 21)开始,当屏幕未上锁且亮屏时,通知可以以小窗口形式显示。用户可以在不离开当前应用前提下操作该通知。
如图:
这里写图片描述

NotificationCompat.Builder mNotifyBuilder = 
    new NotificationCompat.Builder(this)
        .setContentTitle("New Message")
        .setContentText("You've received new messages.")
        .setSmallIcon(R.drawable.ic_notify_status)
        .setFullScreenIntent(pendingIntent, false);

以下两种情况会显示浮动通知:
setFullScreenIntent(),如上述示例。
通知拥有高优先级且使用了铃声和振动

锁屏通知
Android 5.0(API level 21)开始,通知可以显示在锁屏上。用户可以通过设置选择是否允许敏感的通知内容显示在安全的锁屏上。
你的应用可以通过setVisibility()控制通知的显示等级:
VISIBILITY_PRIVATE : 显示基本信息,如通知的图标,但隐藏通知的全部内容
VISIBILITY_PUBLIC : 显示通知的全部内容
VISIBILITY_SECRET : 不显示任何内容,包括图标

你可能感兴趣的:(android,android)