创建自定义大通知
Posted
技术标签:
【中文标题】创建自定义大通知【英文标题】:Create Custom Big Notifications 【发布时间】:2014-02-09 19:53:52 【问题描述】:我想创建一个包含一些控件的通知。由于文本和控件很小,默认通知大小(64dp),我希望它大于默认大小。 可以创建更大的通知,我认为也可以有自定义布局,但我不知道如何。
更具体地说,以下屏幕截图显示了来自 spotify 的通知(图片来自here):
如您所见,大小比默认值大。此外,它还有一些没有文本的 ImageButtons - 如果您使用 Notification.Builder.addAction(),您可以提供一个图标,但还需要提供一个 CharSequence 作为描述 - 如果您将描述留空,仍然会为文本保留空间如果你传递null,它会崩溃。
谁能告诉我如何使用自定义布局创建大通知?
谢谢
【问题讨论】:
Create custom notification, android的可能重复 @phemt.latd 该问题中给出的答案涉及自定义通知默认大小或默认通知大大小。我无法用给定的答案来定制一个大尺寸的通知。 【参考方案1】:因 API 更改而更新:
从 API 24 开始,Notification.Builder
包含一个 setCustomBigContentView(RemoteViews) 方法。 NotificationCompat.Builder(support.v4 包的一部分)也包含此方法。
请注意,NotificationCompat.Builder.setCustomBigContentView 的文档指出:
提供自定义 RemoteView 以代替扩展表单中的平台模板使用。这将覆盖由此 Builder 对象构建的扩展布局。 JELLY_BEAN 之前的版本无操作。
因此,这也仅适用于 API >= 16 (JELLY_BEAN)。
原答案
所以在过度使用谷歌之后,我发现this tutorial 解释了如何使用自定义大布局。诀窍是不要使用setStyle()
,而是手动设置Notification
的bigContentView
字段在构建之后。看起来有点hacky,但这是我最终想出的:
notification_layout_big.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_ <!-- This is where I manually define the height -->
android:orientation="horizontal" >
<!-- some more elements.. -->
</LinearLayout>
在代码中构建Notification
:
Notification foregroundNote;
RemoteViews bigView = new RemoteViews(getApplicationContext().getPackageName(),
R.layout.notification_layout_big);
// bigView.setOnClickPendingIntent() etc..
Notification.Builder mNotifyBuilder = new Notification.Builder(this);
foregroundNote = mNotifyBuilder.setContentTitle("some string")
.setContentText("Slide down on note to expand")
.setSmallIcon(R.drawable.ic_stat_notify_white)
.setLargeIcon(bigIcon)
.build();
foregroundNote.bigContentView = bigView;
// now show notification..
NotificationManager mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotifyManager.notify(1, foregroundNote);
编辑 正如 chx101 所指出的,这只适用于 API >= 16。我没有在这个答案中提到它,但在上面给定的链接教程中提到了它:
在 Android 4.1 JellyBean [API 16] 中首次引入了扩展通知。
【讨论】:
谢谢你。但是如果有另一个通知来了,这个通知的视图会回到默认视图,你能说一下为什么吗? 这是因为 Android 操作系统希望确保所有通知保持可见。您可以使用setPriority-method 增加通知的优先级。但是您永远无法确定您的通知是否已放大。此外,用户始终可以通过向下滑动通知来手动放大通知。 不适用于 API 级别 8。Field requires API level 16 (current min is 8): android.app.Notification#bigContentView
低版本怎么办
@HRaval AFAIK 对于较低的 API 版本,不可能有一个大的自定义通知。但是您可以借助答案here 在运行时检查 API 版本【参考方案2】:
使用 Kotlin 制作自定义通知 dialog_custom_notification
<LinearLayout
android:layout_
android:layout_
android:layout_margin="@dimen/dp_10"
android:background="@drawable/shape_bg_main_notification"
android:gravity="center"
android:orientation="horizontal"
android:padding="@dimen/dp_10">
<LinearLayout
android:layout_
android:layout_
android:layout_gravity="top">
<ImageView
android:id="@+id/ivAppIcon"
android:layout_
android:layout_
android:layout_gravity="top"
android:background="@mipmap/ic_launcher" />
</LinearLayout>
<LinearLayout
android:layout_
android:layout_
android:layout_gravity="top"
android:layout_marginLeft="@dimen/dp_10"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/tvNotificationTitle"
android:layout_
android:layout_
android:text="Notification Tile"
android:textStyle="bold" />
<TextView
android:id="@+id/tvNotificationDescription"
android:layout_
android:layout_
android:layout_marginTop="@dimen/dp_5"
android:text="Notification Description" />
</LinearLayout>
<LinearLayout
android:layout_
android:layout_
android:layout_gravity="top">
<TextView
android:id="@+id/tvDateTime"
android:layout_
android:layout_
android:layout_alignParentRight="true"
android:layout_gravity="top"
android:text="09:50" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
shape_bg_main_notification
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/white" />
<corners android:radius="@dimen/dp_6" />
</shape>
@SuppressLint("WrongConstant")
fun showOfflineNotification(context: Context, title: String, description: String)
val NOTIFICATION_CHANNEL_ID = "com.myapp"
val intent = Intent(context, HomeActivity::class.java)
intent.putExtra("notification", 1)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
if (intent != null)
val pendingIntent = PendingIntent.getActivity(
context, getTwoDigitRandomNo(), intent,
PendingIntent.FLAG_ONE_SHOT
)
val defaultSoundUri =
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val remoteCollapsedViews = RemoteViews(packageName, R.layout.dialog_custom_notification)
remoteCollapsedViews.setTextViewText(R.id.tvNotificationTitle, title)
remoteCollapsedViews.setTextViewText(R.id.tvNotificationDescription, description)
remoteCollapsedViews.setTextViewText(R.id.tvDateTime, getTime())
val notificationBuilder = NotificationCompat.Builder(context)
notificationBuilder.setCustomBigContentView(remoteCollapsedViews)
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher_round)
notificationBuilder.setLargeIcon(
BitmapFactory.de
codeResource(
context.resources,
R.mipmap.ic_launcher
)
)
notificationBuilder.setBadgeIconType(R.mipmap.ic_launcher_round)
notificationBuilder.setContentTitle(title)
if (description != null)
notificationBuilder.setContentText(description)
notificationBuilder.setStyle(
NotificationCompat.BigTextStyle().bigText(description)
)
notificationBuilder.setPriority(NotificationCompat.PRIORITY_HIGH)
notificationBuilder.setAutoCancel(true)
notificationBuilder.setSound(defaultSoundUri)
notificationBuilder.setVibrate(longArrayOf(1000, 1000))
notificationBuilder.setContentIntent(pendingIntent)
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
val importance = NotificationManager.IMPORTANCE_MAX
val notificationChannel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
"NOTIFICATION_CHANNEL_NAME",
importance
)
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.RED
notificationChannel.enableVibration(true)
notificationChannel.vibrationPattern = longArrayOf(1000, 1000)
assert(notificationManager != null)
notificationBuilder.setChannelId(NOTIFICATION_CHANNEL_ID)
notificationManager.createNotificationChannel(notificationChannel)
notificationManager.notify(
getTwoDigitRandomNo()/*Id of Notification*/,
notificationBuilder.build()
)
private fun getTime(): String
val calendar = Calendar.getInstance()
val mdformat = SimpleDateFormat("HH:mm")
val strDate = mdformat.format(calendar.time)
return strDate
fun getTwoDigitRandomNo(): Int
return Random().nextInt(90) + 10
[1]: https://me.stack.imgur.com/rQFP8.png
[1]: https://me.stack.imgur.com/fKM9C.png
【讨论】:
Kotlin 大自定义通知以上是关于创建自定义大通知的主要内容,如果未能解决你的问题,请参考以下文章