最近开发一个app需要显示Notification, 但是这个Notification的title 需要显示成我们另一只app的名字。查找了很多资料,发现如果用系统默认的样式,这是做不到的。所以只能自定义样式。自定义Notification样式要用到RemoteViews,如下:

//自定义的notification, 可以自己指定最上面的Title, 即下面给R.id.tag_tv 控件的字串
    //指定了两个layout ,即一个普通视图,一个是大视图。普通视图content只显示一行,显示不了的有省略号。
    // 大视图content可以显示多行。这种notify 可大可小,自动变化
    @TargetApi(16)
    public static void sendCustomNotifyType(Context context, Intent intent, String content,int notifyId) {
        int iUniqueId = (int) (System.currentTimeMillis() & 0xfffffff);
        //getActivity must set  oneof the params of second (as iUniqueId) and forth(PendingIntent.FLAG_UPDATE_CURRENT)
        //or the Activity while show the same as the first time package.
        PendingIntent contentIntent = PendingIntent.getActivity(context, iUniqueId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        final Notification.BigTextStyle bigTextStyle = new Notification.BigTextStyle();
        Notification.Builder builder = new Notification.Builder(context);
        builder.setOngoing(false);
        builder.setPriority(Notification.PRIORITY_MAX);
        builder.setSmallIcon(R.mipmap.noti_icon);
        builder.setAutoCancel(true);
        builder.setContentIntent(contentIntent);
        bigTextStyle.setBigContentTitle(context.getResources().getString(R.string.asus_mobile_manager));
        bigTextStyle.bigText(content);
        builder.setStyle(bigTextStyle);
        builder.setGroup("demogroup1");//如果不加group, 会导致发送四个Notification就会多一个空的notification出来

        RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.view_notification_type_0_singleline);
        remoteViews.setTextViewText(R.id.tag_tv,context.getResources().getString(R.string.asus_mobile_manager));//Top Title
        remoteViews.setTextViewText(R.id.title_tv,context.getResources().getString(R.string.app_name));//src title
        remoteViews.setTextViewText(R.id.content_tv, content);
        remoteViews.setTextViewText(R.id.time_tv, getTime());
        remoteViews.setImageViewResource(R.id.icon_iv, R.mipmap.app_icon);

        RemoteViews remoteViewsBig = new RemoteViews(context.getPackageName(),R.layout.view_notification_type_0);
        remoteViewsBig.setTextViewText(R.id.tag_tv,context.getResources().getString(R.string.asus_mobile_manager));//Top Title
        remoteViewsBig.setTextViewText(R.id.title_tv,context.getResources().getString(R.string.app_name));//src title
        remoteViewsBig.setTextViewText(R.id.content_tv, content);
        remoteViewsBig.setTextViewText(R.id.time_tv, getTime());
        remoteViewsBig.setImageViewResource(R.id.icon_iv, R.mipmap.app_icon);

        builder.setCustomBigContentView(remoteViewsBig);
        builder.setCustomContentView(remoteViews);

        Notification notification = builder.build();

        /*if(android.os.Build.VERSION.SDK_INT >= 16) {
           notification = builder.build();
           notification.bigContentView = remoteViews;

        }
        notification.contentView = remoteViews;
        */
        NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        //notify id 如果相同,则不管调用几次这个函数,最后,都只出来一个notification
        if(notifyId == 0)
            manager.notify(iUniqueId, notification);
        else
            manager.notify(notifyId, notification);
    }

其中R.layout.view_notification_type_0的定义如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="12dp"
    android:paddingBottom="12dp"
    android:id="@+id/notice_view">

    <LinearLayout android:id="@+id/title_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center_vertical"
        android:paddingStart="10dip"
        android:paddingEnd="10dip">
        <ImageView android:id="@+id/icon_iv"
            android:layout_width="26dp"
            android:layout_height="26dp"
            android:scaleType="fitCenter"
            android:padding="4dp"
            />
        <TextView
            android:id="@+id/tag_tv"
            android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:singleLine="true"
            android:ellipsize="marquee"
            android:fadingEdge="horizontal"
            android:layout_marginLeft="2dp"
            />
        <TextView
            android:id="@+id/time_tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="10sp"
            android:gravity="right"
            android:paddingTop="2dip"
            android:paddingBottom="1dip"
            android:paddingStart="14dip"
            android:textAppearance="@android:style/TextAppearance.Material.Notification.Time"
            android:layout_centerVertical="true"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp"
            />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_marginLeft="16dp"
        android:layout_gravity="center_vertical">

        <TextView
            android:id="@+id/title_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"
            android:layout_marginRight="16dp"
            android:layout_marginTop="-1dp"
            android:layout_marginBottom="-1dp"
            android:fadingEdge="horizontal"
            android:ellipsize="marquee"
            android:layout_weight="1"
            />

        <TextView
            android:id="@+id/content_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="@android:style/TextAppearance.Material.Notification.Title"
            android:layout_marginRight="16dp"
            android:layout_marginTop="-1dp"
            android:layout_marginBottom="-1dp"
            android:fadingEdge="horizontal"
            android:ellipsize="marquee"
            android:layout_weight="1"
            />
    </LinearLayout>
</LinearLayout>

我们主要就是用这个layout创建一个RemoteViews, 然后用这个RemoteViews 替换Notification 的contentView

要强调的几点是,
1.设置bigstyle ,如果你的content字串过长,而又不设置bigstyle,那就会只显示一半,像是被从上往下压得只剩一半了。或者设置了bigstyle, 但是bigcontentview 和contentview用同一个Remoteview, 也会有同样的问题,因为通知多了以后,下面的通知即使是bigstyle, 给的空间仍会变小。所以,我们需要给contentview,和bigcontentview同时指定一个Remoteview, 且,前者content可以只显示一行, 后者content 可以显示多行。这样,你的通知就可以自动根据不同位置,不同空间,应用不同的显示样式。即空间大时,content可以全部显示出来。空间小时,只显示单行,后面加一个省略号,表示后面还有内容。

 2,要setGroup也很重要,如上面所注,如果不设置group, 会导致发送四个Notification后就会多一个空的notification出来,这个空notification点上去没有反应,而且title是我们的app name.
3. pendingIntent.getActivity(), 要指定最后一个参数PendingIntent.FLAG_UPDATE_CURRENT,否则,点击通知时,打开的Activity 内容不会刷新。
4. manager.notify(notifyId, notification);这个notifyId,如果每次发通知这个id相同,则只显示最后一次发的,即只保留一个。只有每次id不一样,才可都保留下来,这就用到了上面第2点的setgroup,否则就有空通知出来的可能。