我想在我的应用中显示消息通知。在以前的Android版本中,一切都很好,但在Lollipop中,通知背景是白色的。
我在layout_message_notification.xml
中使用了这个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>
我在棒棒糖中的通知显示如下:
如何使通知背景变暗或透明,就像以前版本的Android一样?
答案 0 :(得分:7)
最后,如果您想关注官方材料设计specification
始终将样式资源用于自定义通知的文本
并使用您的通知的自定义布局,您可能会考虑不覆盖默认背景,但由于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>
答案 1 :(得分:6)
这个答案描述了一种改变通知背景颜色的 hacky 方法 注意:这是一个无证的解决方法;它基于反射,可能会在自定义固件上被破坏;它仅适用于Android Lollipop和Marshmallow版本;在Android N及更高版本上无效。我建议坚持使用默认颜色,除非你有充分的理由避免它。
<强> WHY 强>
没有合法的方法为自定义通知设置背景颜色。根据 Material Design ,Google决定通知必须为白色或浅灰色,具体取决于其优先级。但是,Google也对此规则提出了两个例外:
MediaStyle
创建的通知可以是任何颜色。由于第二个例外,这种限制看起来不合逻辑且不合理,这是唯一可能的借口,为什么你仍然想要使用自定义颜色而不是谷歌推荐(或强制?)的颜色。 / p>
内在的内容
让我们看看BaseStatusBar
,看看如何施加这种限制。计算通知背景颜色的唯一位置是applyColorsAndBackgrounds method
if
语句的第一个分支用于遗留应用程序。到达此处的唯一方法是将应用程序的目标SDK设置为Build.VERSION_CODES.LOLLIPOP
以下。在这种情况下,背景将变为黑色
我们对entry.row.setTintColor
声明感兴趣。为了达到它,应该通过几个检查,包括isMediaNotification method中包含的检查。他们在这里:
com.android.internal.R.id.status_bar_latest_event_content
作为其ID。com.android.internal.R.id.media_actions
作为其ID的小部件。 如何强>
最有问题的是ID,只要它们在内部资源中声明,并且无法从应用程序的布局XML访问。
第二个问题是通知中使用的RemoteViews
只是应用程序中布局资源的ID,不能在代码中构造。因此,我们无法添加具有通过上述所有检查所需的ID的布局。
但是,Google将addView
和removeAllViews
方法添加到RemoteViews
中以满足他们的需求(在MediaStyle
通知中使用它们)并忘记将其设为私有。< / p>
所以,最后的想法很简单:
removeAllViews
addView
media_actions
的Google定义的布局添加到自定义布局中的隐藏视图(通过第3次检查)缺点:
<强>解强>
我们的自定义大视图必须包含FrameLayout
,其中android.R.id.empty
为其ID。实际上,这里可以使用任何ID,只需确保在代码中引用相同的ID(见下文)。
// 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文件中搜索适当的一个here。但是不要忘记将media_actions
放入层次结构中。
答案 2 :(得分: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"> //...