持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
1、什么是通知栏
通知栏是在应用界面外部显示消息的组件,用于向用户推送消息,用户可以通过点击通知栏直接进入应用的某个页面。
Android系统内置了通知的系统模板,通过模板可以轻松实现通知栏,且不需要对各个品牌的手机进行适配。但同时也开放了自定义通知栏,可以通过RemoteViews实现。
2、自定义通知栏的实现以及注意事项(布局、主题)
自定义通知栏主要通过NotificationCompat.Builder.setCustomContentView(RemoteViews)进行实现:
public static void showEnterAppNotification(Context context) {
//获取NotificationManager
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
//创建RemoteViews,第二个参数填入自定义的布局文件,注意RemoteViews不支持ConstraintLayout
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.view_notification);
//将remoteViews设置进builder
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setOnlyAlertOnce(true)
.setWhen(System.currentTimeMillis())
.setShowWhen(true)
.setSmallIcon(R.mipmap.ic_small_logo)
.setAutoCancel(true)
.setOngoing(true)
.setCustomContentView(remoteViews);
//设置优先级
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
builder.setPriority(NotificationManager.IMPORTANCE_HIGH);
} else {
builder.setPriority(Notification.PRIORITY_HIGH);
}
//设置点击通知栏要跳转的Activity
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra(Constants.EXTRA.NOTIFICATION_FROM, Constants.NotificationType.FROM_NOTIFICATION);
intent.putExtra(Constants.EXTRA.NOTIFICATION_TYPE, NOTIFICATION_CODE);
PendingIntent pendingIntent = PendingIntent.getActivity(context, NOTIFICATION_CODE, intent, PendingIntent.FLAG_CANCEL_CURRENT);
builder.setContentIntent(pendingIntent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE);
}
//Android8以上需要设置通知渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel mNotificationChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
mNotificationChannel.setDescription(CHANNEL_DESCRIPTION);
mNotificationChannel.setSound(null, null);
manager.createNotificationChannel(mNotificationChannel);
builder.setChannelId(CHANNEL_ID);
}
//推送通知
manager.notify(NOTIFICATION_CODE, builder.build());
}
注意:
- Android8以上需要为通知创建渠道,通知才能正常推送。为渠道设置优先级和描述,用户可以在设置中根据需要对该渠道的通知进行屏蔽。
- RemoteViews支持的布局和组件有限,如下:
- 如果自定义布局没有设置背景色,会使用系统默认的背景色。需要对布局中所用到的颜色设置日间模式和夜间模式,以适配手机的两种模式。
3、适配到小米手机,
在进行真机测试时,发现小米8手机的自定义通知栏高度被压缩了。通知栏的布局设置了padding,在其他品牌的手机可以正常显示。如果把padding去掉,在小米手机上可以正常显示,高度不会被压缩,且自带padding。但其他品牌的手机通知栏没有自适应padding,非常不美观。从布局上无法解决的问题,可以从代码上进行解决。通过Build.BRAND获取品牌名,直接通过remoteView.setPadding(id,start,top,right,bottom)设置内边距,id直接填写自定义布局最外层组件的id,其他四个参数按照左上右下顺时针的方向填入边距,如下。
//小米:Xiaomi,谷歌:google,OPPO:OPPO,三星:samsung
if (!"Xiaomi".equals(Build.BRAND)) {
int padding = dp2px(context, 16);
remoteViews.setViewPadding(R.id.container, padding, padding, padding, padding);
}
public int dp2px(Context context, float dp) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}