Фон уведомлений в Android Lollipop белый. Как я могу его изменить?
Я хочу показать уведомление для сообщения в своем приложении. В предыдущих версиях Android все в порядке, но в Lollipop фон уведомлений белый.
Я использовал этот XML-код для своего макета уведомлений в layout_message_notification.xml
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_messageNotification"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent">
<LinearLayout
android:layout_width="0dp"
android:layout_weight=".2"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:src="@drawable/message_icon"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_weight=".8"
android:layout_height="wrap_content"
android:background="@android:color/transparent">
<TextView
android:id="@+id/textView_notification_title"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="right|center_vertical"
android:layout_margin="15dp"/>
</LinearLayout>
</LinearLayout>
Мое уведомление в леденец показано следующим образом:
![notification style in lollipop]()
Как сделать фоновое уведомление темным или прозрачным, как в предыдущих версиях Android?
Ответы
Ответ 1
В конце концов, если вы хотите следовать официальной спецификации материала спецификации
Всегда используйте ресурсы стиля для текста настраиваемого уведомления
и использовать пользовательский макет ваших уведомлений, возможно, вам стоит не переопределять фон по умолчанию, а изменить стиль текста из-за версии API. Вы можете достичь этого, создав два файла стиля ресурса и используя их в соответствии с текущей версией API:
<сильные > значения-V21/notification_styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- according to official recommendation custom notifications should has the same text style as default one-->
<style name="NotificationHeader" parent="@android:style/TextAppearance.Material.Notification.Title" />
<style name="NotificationContent" parent="@android:style/TextAppearance.Material.Notification.Line2" />
</resources>
и
<сильные > значения /notification _styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- according to official recommendation custom notifications should has the same text style as default one-->
<style name="NotificationHeader" parent="@android:style/TextAppearance.StatusBar.EventContent.Title" />
<style name="NotificationContent" parent="@android:style/TextAppearance.StatusBar.EventContent" />
</resources>
Ответ 2
В этом ответе описывается метод hacky изменения цвета фона уведомлений.
Обратите внимание: это недокументированное обходное решение; он основан на размышлении и может быть нарушен на пользовательских прошивках; он применим только к версиям Android Lollipop и Marshmallow; он не работает в Android N и более высоких версиях. Я бы рекомендовал придерживаться цвета по умолчанию, если у вас нет серьезных причин его избежать.
Почему
Не существует законного способа установить цвет фона для пользовательского уведомления. Google решил, что уведомления должны быть белого или светло-серого в зависимости от его приоритета в соответствии с Material Design. Однако Google также сделал два исключения из этого правила:
- Уведомления для старых приложений отображаются с черным цветом
фон;
- Уведомления, созданные с помощью
MediaStyle
, могут иметь любой цвет.
В результате второго исключения такое ограничение выглядит нелогичным и необоснованным, и это единственное возможное оправдание, почему вы по-прежнему хотите использовать пользовательский цвет вместо того, который рекомендуется (или принудительно?) Google.
ЧТО ВНУТРИ
Давайте рассмотрим BaseStatusBar
, чтобы узнать, как это ограничение наложено. Единственное место, где вычисляется цвет фона для уведомления, применить методColorsAndBackgrounds.
Первая ветвь оператора if
предназначена для устаревших приложений. Единственный способ получить здесь - установить целевой SDK вашего приложения ниже Build.VERSION_CODES.LOLLIPOP
. В этом случае фон станет черным.
Нас интересует оператор entry.row.setTintColor
. Чтобы достичь этого, необходимо пройти несколько проверок, в том числе тот, который содержится в isMediaNotification method. Вот они:
- Уведомление должно содержать как обычные, так и большие представления.
- Макет верхнего уровня в обоих представлениях должен иметь
com.android.internal.R.id.status_bar_latest_event_content
как его идентификатор.
- Большой макет должен содержать виджет с
com.android.internal.R.id.media_actions
в качестве его идентификатора.
КАК
Наиболее проблематичными являются идентификаторы, если они объявлены во внутренних ресурсах и не могут быть доступны из XML-макета приложения.
Вторая проблема заключается в том, что RemoteViews
, используемый в уведомлении, является всего лишь идентификатором ресурса компоновки в приложении и не может быть сконструирован в коде. В результате мы не можем добавлять макеты с идентификаторами, необходимыми для прохождения всех проверок, упомянутых выше.
Однако Google добавил методы addView
и removeAllViews
в RemoteViews
для своих нужд (они используются в уведомлении MediaStyle
) и забыли сделать их частными.
Итак, окончательная идея проста:
- создать уведомление на основе внутреннего макета, определенного Google (пройти 2-й чек)
- удалите все с помощью
removeAllViews
- добавьте наш собственный макет с помощью
addView
- специальный случай для большого вида: добавьте макет, определенный Google, который содержит
media_actions
для невидимого представления внутри нашего пользовательского макета (чтобы пройти 3-й чек).
Недостатки:
- раздувание неиспользуемых видов (они удаляются сразу после раздувания)
- сложная и более глубокая иерархия раскладки
Решение
Наш пользовательский большой вид должен содержать FrameLayout
с android.R.id.empty
как его идентификатор. Фактически, любой идентификатор может использоваться здесь, просто убедитесь, что вы ссылаетесь на тот же идентификатор в коде (см. Ниже).
// We need theese ids to use internal Android resources
int topId = Resources.getSystem().getIdentifier("status_bar_latest_event_content", "id", "android");
int topBigLayout = Resources.getSystem().getIdentifier("notification_template_material_big_media_narrow", "layout", "android");
int topSmallLayout = Resources.getSystem().getIdentifier("notification_template_material_media", "layout", "android");
RemoteViews viewSmall = ...; // Create our custom view here
RemoteViews viewBig = ...; // Create our custom big view here
// This is invisible inner view - to have media_actions in hierarchy
RemoteViews innerTopView = new RemoteViews("android", topBigLayout);
viewBig.addView(android.R.id.empty, innerTopView);
// This should be on top - we need status_bar_latest_event_content as top layout
RemoteViews topBigView = new RemoteViews("android", topBigLayout);
topBigView.removeAllViews(topId);
topBigView.addView(topId, viewBig);
// This should be on top - we need status_bar_latest_event_content as top layout
RemoteViews topSmallView = new RemoteViews("android", topSmallLayout);
topSmallView.removeAllViews(topId);
topSmallView.addView(topId, viewSmall);
Notification.Builder builder = new Notification.Builder(this);
builder.setSmallIcon(R.drawable.ic_notification)
.setTicker("Some text")
.setColor(0xff000000) // The desired color!
.setContent(topSmallView);
Notification n = builder.build();
n.bigContentView = topBigView;
// Use our notification "n" here as usual
Для управления высотой большого вида можно использовать другой макет вместо notification_template_material_big_media_narrow
на верхнем уровне. Найдите соответствующий здесь среди файлов notification_template_xxx.xml. Но не забывайте о том, чтобы поместить media_actions
в иерархию.
Ответ 3
Это поведение правильное.
Если вы хотите иметь прямой контроль над этим аспектом, я предлагаю вам сделать следующее:
-
Создайте альтернативную версию layout_message_notification.xml
внутри папки res/layout-v21
-
Немного измените эту новую версию, изменив внешний цвет фона :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_messageNotification"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/gray">
//...