Создание пользовательских больших уведомлений
Я хотел создать уведомление, включая некоторые элементы управления. Поскольку текст и элементы управления невелики с размером уведомления по умолчанию (64dp), я хотел бы иметь размер больше, чем размер по умолчанию.
Можно создавать большие уведомления, и я думаю, что возможно иметь собственный макет, но я не знаю, как это сделать.
Чтобы быть более конкретным, на следующем скриншоте показано уведомление от spotify (изображение взято из здесь): ![Spotify notification]()
Как вы можете видеть, размер больше, чем значение по умолчанию. Кроме того, у него есть какие-то ImageButtons без текста - если вы используете Notification.Builder.addAction(), вы можете предоставить значок, но также необходимо предоставить CharSequence в качестве описания - если вы оставите описание пустым, все равно будет зарезервировано место для текста, и если вы передадите значение null, он сработает.
Может ли кто-нибудь сказать мне, как создать большое уведомление с помощью настраиваемого макета?
Спасибо
Ответы
Ответ 1
Обновление из-за изменений API:
Из API 24 on Notification.Builder
содержит метод setCustomBigContentView (RemoteViews). Также этот NotificationCompat.Builder (который является частью пакета support.v4) содержит этот метод.
Обратите внимание, что в документации для NotificationCompat.Builder.setCustomBigContentView указано:
Поставляйте настраиваемые RemoteViews вместо шаблона платформы в развернутой форме. Это переопределит расширенный макет, который в противном случае был бы сконструирован этим объектом Builder. No-op для версий до JELLY_BEAN.
Следовательно, это также будет работать только для API >= 16 (JELLY_BEAN).
Оригинальный ответ
Поэтому после чрезмерного использования google я нашел этот учебник, объясняющий, как использовать пользовательские большие макеты. Хитрость заключается не в том, чтобы использовать setStyle()
, а вручную установить поле bigContentView
Notification
после его создания. Кажется немного взломанным, но это то, что я, наконец, придумал:
notification_layout_big.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp" <!-- 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);
Edit
Как отмечалось в chx101, это работает только для API >= 16. Я не упоминал об этом в этом ответе, но он упоминался в данном связанном учебнике выше:
Расширенные уведомления были впервые представлены в Android 4.1 JellyBean [API 16].
Ответ 2
dialog_custom_notification
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
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_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top">
<ImageView
android:id="@+id/ivAppIcon"
android:layout_width="@dimen/dp_36"
android:layout_height="@dimen/dp_36"
android:layout_gravity="top"
android:background="@mipmap/ic_launcher" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginLeft="@dimen/dp_10"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/tvNotificationTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Notification Tile"
android:textStyle="bold" />
<TextView
android:id="@+id/tvNotificationDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_5"
android:text="Notification Description" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top">
<TextView
android:id="@+id/tvDateTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
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
}