Android 通知(二)— 可展开式通知

1,144 阅读3分钟

App通过通知可以向用户传递重要的实时信息,可传递的信息多种多样,针对不同的信息类型显示不同的通知样式,可以为用户带来更好的体验。本文将介绍如何使用NotificationCompat库中提供的Style将基础通知更改为可展开式通知。

如何创建基础通知请看上一篇文章Android 通知(一)— 基础通知

可展开式通知

有时候仅包含图标、标题、一行文本样式的基础通知无法满足需求,可以使用NotificationCompat库中提供的Style将基础通知更改为可展开式的通知。

大图片

创建通知时设置NotificationCompat.BigPictureStyle,可以为通知添加一个大图,在通知展开时显示大图,折叠时显示缩略图,示例代码如下:

class NotificationExampleActivity : AppCompatActivity() {

    ......

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ......

        binding.btnCreatePictureNotification.setOnClickListener {
            if (notificationEnable()) {
                ContextCompat.getDrawable(this, R.drawable.big_picture_example)?.also { bigPictureExample ->
                    val emptyIcon: Icon? = null
                    val notificationBuilder = NotificationCompat.Builder(this, "system_error_notification_channel")
                        .setSmallIcon(R.drawable.notification)
                        .setContentTitle("Big picture Notification")
                        .setContentText("This is a big picture notification example.")
                        // 折叠状态下的图标
                        .setLargeIcon(toBitmap(bigPictureExample, DensityUtil.dp2Px(24), DensityUtil.dp2Px(24)))
                        .setStyle(NotificationCompat.BigPictureStyle()
                            // 展开状态下的大图
                            .bigPicture(toBitmap(bigPictureExample))
                            // 传入null可以隐藏折叠状态下的图标(按需使用)
                            // 入参为Icon和入参为Bitmap的bigLargeIcon重载方法都允许传null,并且都只有一个参数
                            // 直接传null会提示匹配到了多个方法
                            .bigLargeIcon(emptyIcon))
                        .setAutoCancel(false)
                    val notificationId = 10001
                    notificationManagerCompat.notify(notificationId, notificationBuilder.build())
                }
            }
        }
    }

    ......

    private fun toBitmap(drawable: Drawable, iconWidth: Int = 0, iconHeight: Int = 0): Bitmap {
        val width = if (iconWidth == 0) drawable.minimumWidth else iconWidth
        val height = if (iconHeight == 0) drawable.minimumHeight else iconHeight
        val oldBounds = Rect(drawable.bounds)
        val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        drawable.setBounds(0, 0, width, height)
        drawable.draw(Canvas(bitmap))
        drawable.bounds = oldBounds
        return bitmap
    }
}

效果如图:

Screen_recording_202 -original-original.gif

长文本

创建通知时设置NotificationCompat.BigTextStyle,可以为通知添加一段长文本,在通知展开时显示长文本内容,示例代码如下:

class NotificationExampleActivity : AppCompatActivity() {
    
    ......

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ......

        binding.btnCreateTextNotification.setOnClickListener {
            if (notificationEnable()) {
                ContextCompat.getDrawable(this, R.drawable.icon_juejin)?.also { bigPictureExample ->
                    val bigTextExample = ContextCompat.getString(this, R.string.label_notification_big_text_example)
                    val notificationBuilder = NotificationCompat.Builder(this, "system_error_notification_channel")
                        .setSmallIcon(R.drawable.notification)
                        .setContentTitle("Big Text Notification")
                        .setContentText("This is a big text notification example.")
                        .setLargeIcon(toBitmap(bigPictureExample, DensityUtil.dp2Px(24), DensityUtil.dp2Px(24)))
                        .setStyle(NotificationCompat.BigTextStyle()
                            // 设置一段ChatGPT生成的掘金简介
                            .bigText(bigTextExample))
                        .setAutoCancel(false)
                    val notificationId = 10002
                    notificationManagerCompat.notify(notificationId, notificationBuilder.build())
                }
            }
        }
    }

    ......
}

效果如图:

Screen_recording_202 -original-original.gif

文本样式调整

可以通过SpannableStringBuilder为长文本添加格式(例如加粗、斜体、改颜色等),示例代码如下:

class NotificationExampleActivity : AppCompatActivity() {

    ......

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ......

        binding.btnCreateTextNotification.setOnClickListener {
            if (notificationEnable()) {
                ContextCompat.getDrawable(this, R.drawable.icon_juejin)?.also { bigPictureExample ->
                    val bigTextExample = ContextCompat.getString(this, R.string.label_notification_big_text_example)
                    val bigTextExampleSpannableString = SpannableStringBuilder(bigTextExample).apply {
                        // 前六个字符改为蓝色
                        setSpan(ForegroundColorSpan(ContextCompat.getColor(this@NotificationExampleActivity, R.color.color_blue_229CE9)), 0, 6, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
                    }
                    val notificationBuilder = NotificationCompat.Builder(this, "system_error_notification_channel")
                        .setSmallIcon(R.drawable.notification)
                        .setContentTitle("Big Text Notification")
                        .setContentText("This is a big text notification example.")
                        .setLargeIcon(toBitmap(bigPictureExample, DensityUtil.dp2Px(24), DensityUtil.dp2Px(24)))
                        .setStyle(NotificationCompat.BigTextStyle()
                            // 设置一段ChatGPT生成的掘金简介
                            .bigText(bigTextExampleSpannableString))
                        .setAutoCancel(false)
                    val notificationId = 10002
                    notificationManagerCompat.notify(notificationId, notificationBuilder.build())
                }
            }
        }
    }
    
    ......
}

效果如图:

Screen_recording_202 -original-original.gif

分行文本

创建通知时设置NotificationCompat.InboxStyle,可以为通知添加多段内容文本且每段文本独立一行,在通知展开时显示多段文本内容,示例代码如下:

class NotificationExampleActivity : AppCompatActivity() {

    ......

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ......

        binding.btnCreateSegmentedTextNotification.setOnClickListener {
            if (notificationEnable()) {
                ContextCompat.getDrawable(this, R.drawable.icon_juejin)?.also { bigPictureExample ->
                    val notificationBuilder = NotificationCompat.Builder(this, "system_error_notification_channel")
                        .setSmallIcon(R.drawable.notification)
                        .setContentTitle("Segmented Text Notification")
                        .setContentText("This is a segmented text notification example.")
                        .setLargeIcon(toBitmap(bigPictureExample, DensityUtil.dp2Px(24), DensityUtil.dp2Px(24)))
                        .setStyle(NotificationCompat.InboxStyle()
                            .addLine("line 1 message")
                            .addLine("line 2 message")
                            .addLine("line 3 message")
                            .addLine("line 4 message")
                            .addLine("line 5 message")
                            .addLine("line 6 message")
                            .addLine("line 7 message")
                        )
                        .setAutoCancel(false)
                    val notificationId = 10003
                    notificationManagerCompat.notify(notificationId, notificationBuilder.build())
                }
            }
        }
    }
    
    ......
}

PS:官方文档提示调用addLine添加新行时,如果超过6次,仅有前六次添加的会显示,但是实测超过6次也是可以完整显示。

效果如图:

Screen_recording_202 -original-original.gif

完整示例代码

所有演示代码已在示例Demo中添加。

ExampleDemo github

ExampleDemo gitee