前言
在运用的开发中,咱们必然会接触到运用告诉这个知识,而在告诉是跟着Android版别进行不断改变,为了能在高版别和低版别中运用,就需求开发者去做适配,也归于查漏补缺。了解之前,先看一个作用图吧。
正文
告诉的运用的内容仍是比较多的,此篇文章将会尽或许详细的介绍Notification的内容。
一、Android中告诉的改变
1. Android 4.1,API 16
- 推出了打开式告诉模板(称为告诉款式),能够供给较大的告诉内容区域来显现信息。
- 用户能够经过单指向上/向下滑动的手势来打开告诉。还支撑以按钮的形式向告诉增加其他操作。
- 允许用户在设置中按运用封闭告诉。
2. Android 4.4,API 19 和 20
- 向 API 中增加了告诉监听器服务。
- API 等级 20 中新增了 Android Wear(现已更名为 Wear OS)支撑。
3. Android 5.0,API 21
- 推出了锁定屏幕和提示式告诉。
- 用户现在能够将手机设为勿扰形式,并装备允许哪些告诉在设备处于“仅限优先事项”形式时打扰他们。
- 向 API 集增加了告诉是否在锁定屏幕上显现的办法 (setVisibility()),以及指定告诉文本的“公开”版其他办法。
- 增加了 setPriority() 办法,告知体系告诉的“干扰性”(例如,将其设为“高”可使告诉以提示式告诉的形式显现)。
- 向 Android Wear(现已更名为 Wear OS)设备增加了告诉仓库支撑。运用 setGroup() 将告诉放入仓库。请留意,平板电脑和手机尚不支撑告诉仓库。告诉仓库以后会称为组或 Bundle。
4. Android 7.0,API 24
- 重新设置了告诉模板的款式以强调主打图片和头像。
- 增加了三个告诉模板:一个用于短信运用,另外两个用于借助打开式选项和其他体系装修来装修自界说内容视图。
- 向手持设备(手机和平板电脑)增加了对告诉组的支撑。运用与 Android 5.0(API 等级 21)中推出的 Android Wear(现已更名为 Wear OS)告诉仓库相同的 API。
- 用户能够运用内嵌回复功用直接在告诉内进行回复(他们输入的文本将转发到告诉的父运用)。
5. Android 8.0,API 26
- 必须将各个告诉放入特定途径中。
- 用户能够按途径封闭告诉,而非封闭来自某个运用的所有告诉。
- 包含有用告诉的运用将在主屏幕/发动器屏幕上相应运用图标的上方显现告诉“标志”。
- 用户能够从抽屉式告诉栏中暂停某个告诉。您能够为告诉设置主动超时时刻。
- 您还能够设置告诉的布景色彩。
- 部分与告诉行为相关的 API 已从 Notification 移至 NotificationChannel。例如,在搭载 Android 8.0 及更高版其他设备中,运用 NotificationChannel.setImportance(),而非 NotificationCompat.Builder.setPriority()。
6. Android 12.0,API 31
- 自界说告诉,供给告诉模板。
- 更改了彻底自界说告诉的外观和行为。
下面就开端咱们的适配之旅吧。
二、创立项目
新建一个名为NotificationStudy的项目,如下图所示:
点击Finish完结项目创立,然后在app的build.gradle中的android{}闭包中敞开viewBinding,代码如下:
buildFeatures {
viewBinding true
}
项目创立好之后,咱们首要改动一下activity_main.xml布局。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_show"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="显现告诉"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
放一个按钮,然后再修正一下MainActivity中的代码,如下所示:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
//显现告诉
binding.btnShow.setOnClickListener {
}
}
}
这儿便是绑定ViewBinding,然后设置按钮点击监听,下面咱们就要开端做显现告诉的操作了。
三、显现告诉
惯例的告诉由三个内容构成:标题、内容和图标。在8.0中还有一个告诉途径,所以咱们需求先创立一个告诉途径。
① 创立告诉途径
创立告诉途径需求三个参数,途径ID、途径称号和途径重要性。
首要在MainActivity中增加几个变量。
//途径Id
private val channelId = "test"
//途径名
private val channelName = "测验告诉"
//途径重要级
private val importance = NotificationManagerCompat.IMPORTANCE_HIGH
//告诉管理者
private lateinit var notificationManager: NotificationManager
//告诉
private lateinit var notification: Notification
//告诉Id
private val notificationId = 1
发送告诉首要要经过告诉服务得到告诉管理者,在onCreate办法中增加如下代码:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
//获取体系告诉服务
notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
...
}
}
然后是创立告诉途径,在MainActivity中新增如下函数。
/**
* 创立告诉途径
*/
@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(channelId: String, channelName: String, importance: Int) =
notificationManager.createNotificationChannel(NotificationChannel(channelId, channelName, importance))
因为告诉途径是Android8.0才有的,因而咱们增加一个注解,然后将数据构建告诉途径的参数传入进来,留意咱们经过notificationManager的createNotificationChannel()函数去创立途径的,假如notificationManager没有初始化的话,毫无疑问你的这一行代码会报错。
② 初始化告诉
告诉途径创立好了,下面咱们去初始化告诉,同样在MainActivity中新增一个initNotification()函数,代码如下:
/**
* 初始化告诉
*/
private fun initNotification() {
notification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//创立告诉途径
createNotificationChannel(channelId,channelName,importance)
NotificationCompat.Builder(this, channelId)
} else {
NotificationCompat.Builder(this)
}.apply {
setSmallIcon(R.mipmap.ic_launcher)//小图标(显现在状态栏)
setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))//大图标(显现在告诉上)
setContentTitle("打工人")//标题
setContentText("我要搞钱!!!")//内容
}.build()
}
这儿首要经过版别判别查看是否需求创立告诉途径,然后会得到一个告诉的Builder,经过Builder去装备告诉所需求的基本参数,这儿我设置了图标,标题,内容,装备完之后调用build(),完结告诉的构建,最终回来一个notification,现在咱们的告诉就构建好了。
③ 显现告诉
然后咱们再修正一下onCreate中的代码,如下所示
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
//获取体系告诉服务
notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
//初始化告诉
initNotification()
//显现告诉
binding.btnShow.setOnClickListener {
notificationManager.notify(notificationId, notification)
}
}
这儿咱们调用了initNotification()函数,然后在点击按钮时发送告诉。
binding.btnShow.setOnClickListener {
notificationManager.notify(notificationId, notification)
}
运转一下,作用如下图所示:
四、告诉点击
在上面的gif中,咱们成功显现了告诉,其中咱们尝试去做了点击告诉的动作,可是没有什么反应,因为这方面的功用还没有写,下面咱们就来写。
首要要想一下点击之后要干嘛?通常来说都是跳转到指定的Activity,咱们当时只有一个MainActivity,因而咱们需求创立一个。
① 创立目的Activity
咱们在com.llw.notification下创立DetailsActivity,对应activity_details.xml布局文件,修正一下布局文件,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DetailsActivity">
<TextView
android:id="@+id/tv_notification_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
这儿增加一个TextView,然后回到DetailsActivity中,修正代码如下:
class DetailsActivity : AppCompatActivity() {
private lateinit var binding: ActivityDetailsBinding
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDetailsBinding.inflate(layoutInflater)
setContentView(binding.root)
intent?.let {
binding.tvNotificationContent.text =
"${it.getStringExtra("title")}\n" + "${it.getStringExtra("content")}"
}
}
}
这儿的代码也很简单,便是获取传递过来的intent中携带的参数显现在TextView上,假设咱们在MainActivity中点击时传递title和content。
② PendingIntent运用
咱们常常运用Intent,可是接触PendingIntent是比较少的,PendingIntent能够看作是对Intent的一个封装,但它不是立刻履行某个行为,而是满意某些条件或触发某些事件后才履行指定的行为。
PendingIntent获取有三种方法:Activity、Service和BroadcastReceiver获取。PendingIntent有一个比较简单的运用方法,例如咱们现在要在Activity中运用,修正initNotification()函数中的代码:
private fun initNotification() {
val title = "打工人"
val content = "我要搞钱!!!"
// 为DetailsActivity 创立显式 Intent
val intent = Intent(this, DetailsActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
putExtra("title", title).putExtra("content", content)
}
val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
notification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//创立告诉途径
createNotificationChannel(channelId, channelName, importance)
NotificationCompat.Builder(this, channelId)
} else {
NotificationCompat.Builder(this)
}.apply {
setSmallIcon(R.mipmap.ic_launcher)//小图标(显现在状态栏)
setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))//大图标(显现在告诉上)
setContentTitle(title)//标题
setContentText(content)//内容
setContentIntent(pendingIntent)//设置内容意图
}.build()
}
这儿的代码解释一下,首要将title、content抽离出来,然后创立intent,再创立pendingIntent 。最终在装备build中设置setContentIntent(pendingIntent),下面咱们运转一下。
这儿现已完结了点击告诉并传递的操作,这儿还有一个细节便是惯例来说咱们点击了这个告诉表明咱们现已看到了,或许现已知晓了内容,因而告诉就会消失,而这儿告诉并没有音讯。
只需求一个装备就能够做到。
setAutoCancel(true)//设置主动撤销
增加方位如下图所示:
运转测验一下就行,我就不用gif阐明了。
五、折叠告诉
有时分咱们设置告诉的内容或许一行放不下,这个时分就需求收缩和打开告诉,让用户看到完整的信息。
① 长文本
现在我将content的内容修正一下:
val content = "我要搞钱!!!富足、明主、文明、调和、自由、平等、公平、法治、爱国、敬业、诚信、友善"
然后咱们什么都不做去运转看看。
这儿并没有显现多行,一起也没有那个向下打开的按钮,内容文字做了省掉,因而这阐明那个打开需求咱们去设置。
一行代码搞定:
setStyle(NotificationCompat.BigTextStyle().bigText(content))
经过设置告诉的风格款式,这儿运用的是长文本信息款式,将content传递进去。增加方位如下图所示:
运转一下看看
② 显现图片
有时分咱们会在告诉中打开时看到图片,实际上便是运用了另一个款式,也是一行代码解决。
setStyle(NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(resources,R.drawable.logo)))//设置款式
这行代码的方位和替换掉方才哪一行,告诉只能设置一个款式,后边设置的款式会覆盖掉前面的款式,这儿咱们运用大图片款式,传进入一个logo.jpg图片,你在写的时分随便用什么都行,然后咱们再运转一下。
六、回复告诉
有时分咱们的手机收到短信音讯,是能够直接回复的。当然了这个功用是需求手动去写的。流程便是点击按钮出现一个告诉,告诉中回复音讯,播送或服务收到音讯后更新告诉,然后封闭告诉。
① 创立播送
这儿咱们先来写这个接收回复音讯的处理,这儿用播送来处理,首要咱们需求创立一个播送,在com.llw.notification下新建一个ReplyMessageReceiver类,里边的代码如下:
class ReplyMessageReceiver : BroadcastReceiver() {
private val TAG = ReplyMessageReceiver::class.java.simpleName
override fun onReceive(context: Context, intent: Intent) {
//获取回复音讯的内容
val inputContent =
RemoteInput.getResultsFromIntent(intent)?.getCharSequence("key_text_reply")?.toString()
Log.d(TAG, "onReceive: $inputContent")
if (inputContent == null) {
Log.e(TAG, "onReceive: 没有回复音讯!")
return
}
//构建回复音讯告诉
val repliedNotification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationCompat.Builder(context, "reply")
} else {
NotificationCompat.Builder(context)
}.apply {
setSmallIcon(R.mipmap.ic_launcher)//小图标(显现在状态栏)
setContentTitle("1008666")//标题
setContentText("音讯发送成功!")//内容
}.build()
val notificationManager =
context.getSystemService(AppCompatActivity.NOTIFICATION_SERVICE) as NotificationManager
//发送告诉
notificationManager.notify(2, repliedNotification)
//1秒后撤销告诉
Timer().schedule(1000){
notificationManager.cancel(2)
}
}
}
这儿阐明一下:首要是RemoteInput表明长途输入,也便是告诉栏上输入框,这儿便是获取输入框的内容,留意”key_text_reply”这个值,咱们在构建RemoteInput时运用的值要与这个一致,不一致你在播送中就拿不到输入的值。
然后是构建告诉了,这儿的设置都是惯例操作,途径id我是写死的,因而在Activity中创立告诉时途径Id也要一致。最终便是在发送告诉之后加了一个1秒的延时去撤销告诉,表明收到回复的处理。
播送是需求在AndroidManifest.xml注册的,代码如下:
<receiver android:name=".ReplyMessageReceiver"/>
方位如下:
下面便是要构建回复告诉了。因为要区别于之前的一般告诉,所以这儿我需求更改一下activity_main.xml中的布局代码
<Button
android:id="@+id/btn_show_reply"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="显现回复告诉"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_show" />
增加一个按钮,点击事件后边再写。
② RemoteInput
为了区别一般告诉和回复告诉,在MainActivity中界说一下。
//回复告诉Id
private val replyNotificationId = 2
//回复告诉
private lateinit var replyNotification: Notification
下面咱们新建一个initReplyNotification()函数,在里边对RemoteInput进行构建。
private fun initReplyNotification() {
//长途输入
val remoteInput = RemoteInput.Builder("key_text_reply").setLabel("快速回复").build()
}
这儿RemoteInput的构建也很简单,最要害的便是”key_text_reply”,方才在适配器中现已说了,而Label便是一个输入框的提示文本。
③ PendingIntent
现在咱们要经过BroadcastReceiver获取PendingIntent,在initReplyNotification()函数中新增代码:
private fun initReplyNotification() {
...
//构建回复pendingIntent
val replyIntent = Intent(this, ReplyMessageReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(this, 0, replyIntent, PendingIntent.FLAG_ONE_SHOT)
}
④ NotificationCompat.Action
告诉动作,咱们在输入框写入信息,需求一个按钮发送这个按钮,这个Action便是用来做这个工作的,在initReplyNotification()函数中新增代码:
private fun initReplyNotification() {
...
//点击告诉的发送按钮
val action = NotificationCompat.Action.Builder(0, "回复", pendingIntent).addRemoteInput(remoteInput).build()
}
⑤ 构建告诉
下面便是构建告诉,在initReplyNotification()函数中新增代码:
private fun initReplyNotification() {
...
//构建告诉
replyNotification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel("reply", "回复音讯", importance)
NotificationCompat.Builder(this, "reply")
} else {
NotificationCompat.Builder(this)
}.apply {
setSmallIcon(R.mipmap.ic_launcher)//小图标(显现在状态栏)
setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))//大图标(显现在告诉上)
setContentTitle("1008666")//标题
setContentText("你的账号已欠费2000元!")//内容
addAction(action)
}.build()
}
这儿的要害就在于这个addAction(action),下面咱们运转一下:
然后咱们看看日志:
七、横幅告诉
横幅告诉我相信你必定见过,例如收到短信、QQ、微信、钉钉的音讯,都会有出现在屏幕顶部,主要是用于提示用户的。
首要咱们修正布局,在activity_main.xml中新增一个按钮,代码如下:
<Button
android:id="@+id/btn_show_banner"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="显现横幅告诉"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_show_reply" />
① 查看横幅告诉是否打开
首要在MainActivity中界说几个变量
//横幅告诉
private lateinit var bannerNotification: Notification
//横幅告诉Id
private val bannerNotificationId = 3
//敞开横幅告诉回来
private val bannerLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == RESULT_OK) {
Log.d("TAG", "回来成果")
}
}
然后新增一个openBannerNotification()函数,代码如下:
private fun openBannerNotification() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val bannerImportance = notificationManager.getNotificationChannel("banner").importance
if (bannerImportance == NotificationManager.IMPORTANCE_DEFAULT) {
val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
.putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
.putExtra(Settings.EXTRA_CHANNEL_ID, "banner")
bannerLauncher.launch(intent); false
} else true
} else true
这儿经过查看告诉遇到的重要级判别是否敞开横幅告诉。
② 构建横幅告诉途径
在MainActivity中新增createBannerNotificationChannel()函数,代码如下:
@RequiresApi(Build.VERSION_CODES.O)
private fun createBannerNotificationChannel(channelId: String, channelName: String, importance: Int) =
notificationManager.createNotificationChannel(
NotificationChannel(channelId, channelName, importance).apply {
description = "提示式告诉"//途径描绘
enableLights(true)//敞开闪光灯
lightColor = Color.BLUE//设置闪光灯色彩
enableVibration(true)//敞开轰动
vibrationPattern = longArrayOf(0, 1000, 500, 1000)//轰动形式
setSound(null, null)//没有提示音
}
)
这儿的内容相对于之前来说就多一些,有注释也好理解。
③ 构建横幅告诉
在MainActivity中新增initBannerNotification()函数,代码如下:
private fun initBannerNotification() {
//构建告诉
bannerNotification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createBannerNotificationChannel("banner", "提示音讯", importance)
NotificationCompat.Builder(this, "banner")
} else {
NotificationCompat.Builder(this)
}.apply {
setSmallIcon(R.mipmap.ic_launcher)//小图标(显现在状态栏)
setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))//大图标(显现在告诉上)
setContentTitle("落魄Android在线炒粉")//标题
setContentText("不要9块9,不要6块9,只需3块9。")//内容
setWhen(System.currentTimeMillis())//告诉显现时刻
setAutoCancel(true)//设置主动撤销
}.build()
}
这儿也便是一些惯例的设置。
④ 显现横幅告诉
最终咱们在onCreate()函数中,新增如下代码:
//显现横幅告诉
binding.btnShowBanner.setOnClickListener {
//查看是否授予访问权限
if (openBannerNotification()) {
notificationManager.notify(bannerNotificationId, bannerNotification)
}
}
下面咱们运转一下:
OK,这样就能够了。
八、常驻告诉
咱们知道有一些告诉,当程序运转的时分就会出现,例如咱们最常见的音乐类App,而且这个告诉并不是马上出现的,在此之前还有许多内容要初始化,一切就绪之后出现这个告诉,就能够经过告诉去控制音乐了。
咱们并不需求这种杂乱的操作,只有有一个告诉能在App发动的时分显现出来,而且App进入后台时,告诉也还在。
在MainActivity创立变量。
//常驻告诉
private lateinit var permanentNotification:
//常驻告诉Id
private val permanentNotificationId = 4Notification
然后在MainActivity中新增一个showPermanentNotification()函数,代码如下:
private fun showPermanentNotification() {
//构建回复pendingIntent
val permanentIntent = Intent(this, MainActivity::class.java)
val pendingIntent =
PendingIntent.getActivity(this, 0, permanentIntent, PendingIntent.FLAG_UPDATE_CURRENT)
//构建告诉
permanentNotification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel("permanent", "我一直存在", importance)
NotificationCompat.Builder(this, "permanent")
} else {
NotificationCompat.Builder(this)
}.apply {
setSmallIcon(R.mipmap.ic_launcher)//小图标(显现在状态栏)
setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))//大图标(显现在告诉上)
setContentTitle("你在尽力些什么?")//标题
setContentText("搞钱!搞钱!仍是搞钱!")//内容
setWhen(System.currentTimeMillis())//告诉显现时刻
setContentIntent(pendingIntent)
}.build()
permanentNotification.flags = Notification.FLAG_ONGOING_EVENT
notificationManager.notify(permanentNotificationId, permanentNotification)
}
这儿就很简单了,主要便是去掉告诉撤销设置,一起设置FLAG_ONGOING_EVENT,另外在点击告诉的时分进入主页面。在onCreate()函数中调用。
运转一下:
能够看到这儿我用其他告诉显现出来之后,清理一下,其他告诉就没有了,而常驻告诉还在,然后我程序进入后台,点击常驻告诉,又会发动到前台。
九、自界说款式告诉
现在咱们运用的都是惯例的款式告诉,实际上咱们能够自界说的,便是自界说告诉布局,咱们先来规划自界说布局的款式,就做一个音乐告诉栏吧,首要是三个图标。
① 自界说告诉布局
在drawable文件夹下新建ic_previous.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:tint="@color/white"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@android:color/white"
android:pathData="M7,6c0.55,0 1,0.45 1,1v10c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1L6,7c0,-0.55 0.45,-1 1,-1zM10.66,12.82l5.77,4.07c0.66,0.47 1.58,-0.01 1.58,-0.82L18.01,7.93c0,-0.81 -0.91,-1.28 -1.58,-0.82l-5.77,4.07c-0.57,0.4 -0.57,1.24 0,1.64z" />
</vector>
ic_play.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:tint="@color/white"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@android:color/white"
android:pathData="M8,6.82v10.36c0,0.79 0.87,1.27 1.54,0.84l8.14,-5.18c0.62,-0.39 0.62,-1.29 0,-1.69L9.54,5.98C8.87,5.55 8,6.03 8,6.82z" />
</vector>
ic_next.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36dp"
android:height="36dp"
android:tint="@color/white"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@android:color/white"
android:pathData="M7.58,16.89l5.77,-4.07c0.56,-0.4 0.56,-1.24 0,-1.63L7.58,7.11C6.91,6.65 6,7.12 6,7.93v8.14c0,0.81 0.91,1.28 1.58,0.82zM16,7v10c0,0.55 0.45,1 1,1s1,-0.45 1,-1V7c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1z" />
</vector>
然后在layout下新建一个layout_custom_notification.xml,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_song_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="雨下一整晚"
android:textColor="@color/white"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_singer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:text="周杰伦"
android:textColor="@color/white"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center">
<ImageButton
android:id="@+id/iv_previous"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:src="@drawable/ic_previous" />
<ImageButton
android:id="@+id/iv_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="@null"
android:src="@drawable/ic_play" />
<ImageButton
android:id="@+id/iv_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:src="@drawable/ic_next" />
</LinearLayout>
<ImageView
android:id="@+id/iv_avatar"
android:layout_width="72dp"
android:layout_height="72dp"
android:src="@drawable/jay" />
</LinearLayout>
这儿要留意一点自界说告诉的界面布局只支撑LinearLayout、RelativeLayout、FrameLayout,目前不支撑ConstraintLayout告诉布局里有ConstraintLayout的话,弹告诉不会显现。
jpg图标用自己的,或许用我源码里边都能够,然后就很简单了,回到MainActivity。
② 显现自界说告诉
//自界说告诉
private lateinit var customNotification: Notification
//自界说告诉Id
private val customNotificationId = 5
然后创立initCustomNotification()函数,代码如下:
@SuppressLint("RemoteViewLayout")
private fun initCustomNotification() {
//RemoteView
val remoteViews = RemoteViews(packageName, R.layout.layout_custom_notification)
customNotification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel("custom", "自界说告诉", importance)
NotificationCompat.Builder(this, "custom")
} else {
NotificationCompat.Builder(this)
}.apply {
setSmallIcon(R.mipmap.ic_launcher)//小图标(显现在状态栏)
setCustomContentView(remoteViews)//设置自界说内容视图
setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
setOnlyAlertOnce(true)
setOngoing(true)
}.build()
}
在onCreate中调用
然后咱们在activity_main.xml中新增一个按钮:
<Button
android:id="@+id/btn_show_custom"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="显现自界说告诉"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_show_banner" />
最终在MainActivity中的onCreate()函数中新增按钮点击事件,一起点击调用告诉显现:
//显现自界说告诉
binding.btnShowCustom.setOnClickListener {
notificationManager.notify(customNotificationId, customNotification)
}
运转一下:
③ 自界说告诉大小
告诉布局视图布局的高度上限为 64 dp,打开后的视图布局的高度上限为 256 dp,方才咱们只设置了小的告诉,那么假如要打开一个大一点的告诉,最好是能够滑动告诉的时分有大小改变。
其实很简单,首要咱们同样要界说一个大一点同告诉布局,在layout下新建一个layout_custom_notification_big.xml,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black"
android:gravity="center_vertical">
<TextView
android:id="@+id/tv_song_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="雨下一整晚"
android:textColor="@color/white"
android:textSize="20sp" />
<TextView
android:id="@+id/tv_singer"
android:layout_below="@+id/tv_song_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="6dp"
android:text="周杰伦"
android:textColor="@color/white"
android:textSize="16sp" />
<LinearLayout
android:layout_marginTop="16dp"
android:layout_below="@+id/tv_singer"
android:layout_alignParentStart="true"
android:layout_toStartOf="@+id/iv_avatar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center">
<ImageButton
android:id="@+id/iv_previous"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:src="@drawable/ic_previous" />
<ImageButton
android:id="@+id/iv_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="@null"
android:src="@drawable/ic_play" />
<ImageButton
android:id="@+id/iv_next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:src="@drawable/ic_next" />
</LinearLayout>
<ImageView
android:layout_alignParentEnd="true"
android:id="@+id/iv_avatar"
android:layout_width="144dp"
android:layout_height="144dp"
android:src="@drawable/jay" />
</RelativeLayout>
然后咱们修正initCustomNotification()函数中的代码:
@SuppressLint("RemoteViewLayout")
private fun initCustomNotification() {
//RemoteView
val remoteViews = RemoteViews(packageName, R.layout.layout_custom_notification)
val bigRemoteViews = RemoteViews(packageName, R.layout.layout_custom_notification_big)
customNotification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel("custom", "自界说告诉", importance)
NotificationCompat.Builder(this, "custom")
} else {
NotificationCompat.Builder(this)
}.apply {
setSmallIcon(R.mipmap.ic_launcher)//小图标(显现在状态栏)
setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
setCustomContentView(remoteViews)
setCustomBigContentView(bigRemoteViews)
setOnlyAlertOnce(true)
setOngoing(true)
}.build()
}
咱们再创立一个RemoteView,然后经过setCustomBigContentView设置一下就能够了,下面运转一下,看看作用。
十、源码
假如你觉得代码对你有帮助的话,不妨Fork或许Star一下~
GitHub:NotificationStudy