Android自定义通知布局切换系统主题时文字颜色不更新求助
自定义通知布局主题切换后文字颜色不更新的解决方案
问题背景
应用安装后首次启动,浅色/深色主题下自定义通知布局显示正常;但切换系统主题后,通知标题和正文的文字颜色无法自动适配,仅重新安装应用或重置手机后才能恢复,系统默认通知布局无此问题。测试设备为Redmi Note 3Pro(基于AOSP V9的自定义ROM)。
涉及代码
折叠模式布局(notification_collapse.xml)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layoutDirection="rtl" android:layout_width="match_parent" android:layout_height="64dp"> <TextView android:id="@+id/TVNotTitle" style="@style/TextAppearance.Compat.Notification.Title" android:layout_width="wrap_content" android:layout_height="wrap_content" tools:text="عنوان پیام" /> <ImageView android:id="@+id/IVNotif" android:layout_width="40dp" android:layout_height="40dp" android:layout_alignParentEnd="true" tools:src="@drawable/sibil" /> <TextView android:id="@+id/TVNotInfo" style="@style/TextAppearance.Compat.Notification.Info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/TVNotTitle" android:layout_toStartOf="@id/IVNotif" android:ellipsize="end" android:maxLines="1" tools:text="این یک پیام جدید است ..." /> </RelativeLayout>
展开模式布局(notification_expand.xml)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layoutDirection="rtl" android:layout_margin="10dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:maxHeight="256dp"> <TextView android:id="@+id/TVNotTitle" style="@style/TextAppearance.Compat.Notification.Title" android:layout_width="wrap_content" android:layout_height="wrap_content" tools:text="عنوان پیام" /> <ImageView android:id="@+id/IVNotif" android:layout_width="80dp" android:layout_height="80dp" android:layout_alignParentEnd="true" tools:src="@drawable/sibil" /> <TextView android:id="@+id/TVNotInfo" style="@style/TextAppearance.Compat.Notification.Info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/TVNotTitle" android:layout_toStartOf="@id/IVNotif" android:ellipsize="end" android:maxLines="6" tools:text="این یک پیام جدید است ..." /> </RelativeLayout>
通知构建代码
val notification = NotificationCompat.Builder(context, myStructure.channel_id) .setSmallIcon(R.drawable.ic_notification) .setCustomContentView(collapsView) .setCustomBigContentView(expandView) .setStyle(NotificationCompat.DecoratedCustomViewStyle()) .setContentIntent(pendingIntent) notificationManager.notify(1, notification.build())
解决方案
1. 自定义主题适配的通知文本样式
放弃直接使用@style/TextAppearance.Compat.Notification系列样式,手动定义适配浅色/深色主题的文本样式,确保颜色引用系统主题属性:
res/values/styles.xml
<style name="NotificationTitle"> <item name="android:textColor">?android:attr/textColorPrimary</item> <item name="android:textSize">16sp</item> <item name="android:textStyle">bold</item> </style> <style name="NotificationInfo"> <item name="android:textColor">?android:attr/textColorSecondary</item> <item name="android:textSize">14sp</item> </style>
res/values-night/styles.xml
<style name="NotificationTitle"> <item name="android:textColor">?android:attr/textColorPrimaryInverse</item> <item name="android:textSize">16sp</item> <item name="android:textStyle">bold</item> </style> <style name="NotificationInfo"> <item name="android:textColor">?android:attr/textColorSecondaryInverse</item> <item name="android:textSize">14sp</item> </style>
然后替换布局文件中的样式引用:
<TextView android:id="@+id/TVNotTitle" style="@style/NotificationTitle" ... /> <TextView android:id="@+id/TVNotInfo" style="@style/NotificationInfo" ... />
2. 确保视图构建使用主题上下文
构建RemoteViews时,使用ContextThemeWrapper关联当前系统主题,避免应用上下文的主题缓存影响:
val themedContext = ContextThemeWrapper(context, android.R.style.Theme_DeviceDefault) val collapsView = RemoteViews(themedContext.packageName, R.layout.notification_collapse) val expandView = RemoteViews(themedContext.packageName, R.layout.notification_expand)
3. 监听主题变化并刷新通知
注册系统配置变化广播,当主题切换时重新发送通知,强制更新视图样式:
class MyApp : Application() { private lateinit var configReceiver: BroadcastReceiver override fun onCreate() { super.onCreate() configReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action == Intent.ACTION_CONFIGURATION_CHANGED) { context?.let { refreshNotification(it) } } } } registerReceiver(configReceiver, IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED)) } override fun onTerminate() { super.onTerminate() unregisterReceiver(configReceiver) } private fun refreshNotification(context: Context) { val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val collapsView = RemoteViews(context.packageName, R.layout.notification_collapse) val expandView = RemoteViews(context.packageName, R.layout.notification_expand) // 重新设置通知内容(如标题、正文) collapsView.setTextViewText(R.id.TVNotTitle, "最新标题") collapsView.setTextViewText(R.id.TVNotInfo, "最新正文") expandView.setTextViewText(R.id.TVNotTitle, "最新标题") expandView.setTextViewText(R.id.TVNotInfo, "最新正文") val notification = NotificationCompat.Builder(context, myStructure.channel_id) .setSmallIcon(R.drawable.ic_notification) .setCustomContentView(collapsView) .setCustomBigContentView(expandView) .setStyle(NotificationCompat.DecoratedCustomViewStyle()) .setContentIntent(pendingIntent) .build() notificationManager.notify(1, notification) } }
4. ROM兼容性适配(针对自定义AOSP ROM)
由于设备是基于AOSP V9的自定义ROM,可能存在系统通知主题适配bug,可尝试:
- 确保通知通道的重要性设置为
IMPORTANCE_DEFAULT或更高,避免系统强制覆盖样式 - 若需要,在通知构建时添加
setColorized(true)并设置适配主题的颜色,但此操作会改变通知栏背景,按需使用
内容的提问来源于stack exchange,提问作者NimaAzhd
相关产品推荐
相关产品推荐

