跳到主要内容

主题定制

提示

从 5.30.0 版本开始,IMKit 支持主题定制功能,提供传统主题和欢快主题两种内置主题,同时支持自定义主题。

功能概述

IMKit 的主题定制功能提供了灵活的主题配置能力,包括:

  • 内置主题:传统主题(Traditional)和欢快主题(Lively)
  • 自定义主题:支持基于内置主题进行颜色和图片的自定义
  • 深色模式:Android 10+ 自动适配系统深色模式
  • 动态切换:运行时无缝切换主题,无需重启应用

效果预览

传统主题-浅色欢快主题-浅色欢快主题-深色
传统主题-浅色模式-会话列表欢快主题-浅色模式-会话列表欢快主题-深色模式-会话列表

主题资源

IMKit SDK 组件包含所支持的内置主题资源。传统主题资源位于 res 文件夹下,欢快主题资源位于 res-lively 相关文件夹下。

资源路径

欢快主题包含浅色和深色两套资源,分别位于 res-lively-lightres-lively-dark 文件夹下。 每个主题文件夹包含 values 配置文件和 drawable 资源文件夹。 values 文件夹存储了当前主题所使用的颜色、样式等配置; drawable 资源文件夹存储了当前主题所使用的图片资源。

新增主题需要基于内置主题实现,用户需提供包含样式配置文件和资源文件夹的资源包,其中样式配置按需添加,缺失的配置,SDK 会从内置主题浅色资源中获取对应资源替换。

快速开始

使用内置主题

IMKit SDK 默认使用传统主题,您可以通过以下方式切换主题:

Java
import io.rong.imkit.config.IMKitThemeManager;

// 切换到传统主题
IMKitThemeManager.changeInnerTheme(context, IMKitThemeManager.TRADITION_THEME);

// 切换到欢快主题
IMKitThemeManager.changeInnerTheme(context, IMKitThemeManager.LIVELY_THEME);

主题系统架构

核心类说明

IMKitThemeManager

主题管理器,负责主题的切换和资源获取。

主要方法

方法说明
changeInnerTheme(Context, String)切换内置主题
changeCustomTheme(Context, String, String)应用自定义主题
getCurrentThemeName()获取当前主题名称
getAttrResId(Context, int)获取主题属性资源ID
addTheme(String, int, int)添加自定义主题
addThemeListener(OnThemeListener)添加主题变更监听
removeThemeListener(OnThemeListener)移除主题变更监听

主题常量

内置主题类型常量。

Java
public class IMKitThemeManager {
public static final String TRADITION_THEME = "TRADITION_THEME"; // 传统主题
public static final String LIVELY_THEME = "LIVELY_THEME"; // 欢快主题
}

主题切换

应用内置主题

IMKit 提供两种内置主题:传统主题(Traditional)和欢快主题(Lively)。

切换到传统主题

Java
import io.rong.imkit.config.IMKitThemeManager;

// 切换到传统主题
IMKitThemeManager.changeInnerTheme(context, IMKitThemeManager.TRADITION_THEME);

切换到欢快主题

Java
// 切换到欢快主题
IMKitThemeManager.changeInnerTheme(context, IMKitThemeManager.LIVELY_THEME);

获取当前主题

Java
// 获取当前主题名称
String currentTheme = IMKitThemeManager.getCurrentThemeName();
if (IMKitThemeManager.TRADITION_THEME.equals(currentTheme)) {
Log.d("Theme", "当前使用传统主题");
} else if (IMKitThemeManager.LIVELY_THEME.equals(currentTheme)) {
Log.d("Theme", "当前使用欢快主题");
}

深色模式支持

IMKit 会自动适配 Android 10+ 的系统深色模式,无需额外配置。

兼容性说明
  • Android 10+:完整支持深色模式
  • Android 10 以下:仅支持浅色模式

自定义主题

创建自定义主题

步骤 1:准备主题资源

创建主题资源文件夹,包含配置文件和资源文件:

text
app/src/main/
├── res-custom-ocean/ # 通用资源(可选)
│ ├── drawable/
│ └── drawable-xxhdpi/
├── res-custom-ocean-light/ # 浅色主题资源
│ ├── values/
│ │ ├── ocean_colors.xml
│ │ └── ocean_style.xml
│ └── drawable/
└── res-custom-ocean-dark/ # 深色主题资源
├── values/
│ ├── ocean_dark_colors.xml
│ └── ocean_dark_style.xml
└── drawable/

步骤 2:配置 Gradle

build.gradle 中添加资源文件夹:

gradle
android {
sourceSets {
main {
res.srcDirs = [
'src/main/res',
'src/main/res-custom-ocean',
'src/main/res-custom-ocean-light',
'src/main/res-custom-ocean-dark'
]
}
}
}

步骤 3:定义颜色资源

res-custom-ocean-light/values/ocean_colors.xml

xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 主色 -->
<color name="rc_primary_color_ocean_light">#0077BE</color>

<!-- 文字色 -->
<color name="rc_text_primary_color_ocean_light">#1A1A1A</color>
<color name="rc_text_secondary_color_ocean_light">#6B7280</color>

<!-- 功能色 -->
<color name="rc_success_color_ocean_light">#10B981</color>
<color name="rc_hint_color_ocean_light">#EF4444</color>
<color name="rc_disabled_color_ocean_light">#D1D5DB</color>

<!-- 背景色 -->
<color name="rc_common_background_color_ocean_light">#F0F9FF</color>
<color name="rc_auxiliary_background_1_color_ocean_light">#E0F2FE</color>
<color name="rc_line_background_color_ocean_light">#E5E7EB</color>
</resources>

步骤 4:定义样式主题

res-custom-ocean-light/values/ocean_style.xml

xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 自定义海洋主题 -->
<style name="RCOceanLightTheme">
<!-- 主色 -->
<item name="rc_primary_color">@color/rc_primary_color_ocean_light</item>

<!-- 文字色 -->
<item name="rc_text_primary_color">@color/rc_text_primary_color_ocean_light</item>
<item name="rc_text_secondary_color">@color/rc_text_secondary_color_ocean_light</item>

<!-- 功能色 -->
<item name="rc_success_color">@color/rc_success_color_ocean_light</item>
<item name="rc_hint_color">@color/rc_hint_color_ocean_light</item>
<item name="rc_disabled_color">@color/rc_disabled_color_ocean_light</item>

<!-- 背景及线条色 -->
<item name="rc_common_background_color">@color/rc_common_background_color_ocean_light</item>
<item name="rc_auxiliary_background_1_color">@color/rc_auxiliary_background_1_color_ocean_light</item>
<item name="rc_line_background_color">@color/rc_line_background_color_ocean_light</item>

<!-- 图标资源 -->
<item name="rc_navigation_bar_btn_back_img">@drawable/rc_navigation_bar_btn_back_ocean</item>
<item name="rc_navigation_bar_btn_more_img">@drawable/rc_navigation_bar_btn_more_ocean</item>
</style>
</resources>
重要提示:必须使用资源引用

在定义主题样式时,必须使用颜色资源引用(如 @color/rc_primary_color_ocean_light),不要直接使用颜色值(如 #0077BE)。

❌ 错误示例:

xml
<style name="RCOceanLightTheme">
<!-- 不要这样做! -->
<item name="rc_primary_color">#0077BE</item>
</style>

✅ 正确示例:

xml
<style name="RCOceanLightTheme">
<!-- 必须引用颜色资源 -->
<item name="rc_primary_color">@color/rc_primary_color_ocean_light</item>
</style>

使用颜色资源引用的优势:

  • 易于维护:颜色定义集中管理,修改时只需改一处
  • 资源复用:同一颜色可以在多处引用,保持一致性
  • 深浅色适配:配合 values-night 可以自动适配深浅色模式
  • 符合规范:遵循 Android 资源管理最佳实践
  • 避免错误:直接使用颜色值可能导致主题系统无法正确解析资源

步骤 5:注册并使用自定义主题

在 Application 初始化时注册主题:

Java
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();

// 注册自定义主题
IMKitThemeManager.addTheme(
"THEME_OCEAN",
R.style.RCOceanLightTheme, // 浅色样式
R.style.RCOceanDarkTheme // 深色样式
);
}
}

切换到自定义主题:

Java
// 基于欢快主题的自定义主题(推荐)
IMKitThemeManager.changeCustomTheme(
context,
"THEME_OCEAN",
IMKitThemeManager.LIVELY_THEME
);

// 基于传统主题的自定义主题
IMKitThemeManager.changeCustomTheme(
context,
"THEME_OCEAN",
IMKitThemeManager.TRADITION_THEME
);

自定义主题的优先级

自定义主题的资源加载遵循以下优先级:

  1. 自定义主题配置:优先使用自定义主题中配置的颜色和图片
  2. 内置主题配置:如果自定义主题中未配置,则使用内置主题的资源
  3. 默认值:如果无法获取到定义的有效资源,则会返回默认资源

示例

Java
// 假设自定义主题只配置了 rc_primary_color
// 其他颜色会使用基础主题(传统或欢快)的配置

IMKitThemeManager.addTheme(
"PARTIAL_THEME",
R.style.PartialLightTheme,
R.style.PartialDarkTheme
);

IMKitThemeManager.changeCustomTheme(
context,
"PARTIAL_THEME",
IMKitThemeManager.LIVELY_THEME
);

// rc_primary_color 使用自定义主题的配置
// 其他颜色使用欢快主题的配置

动态资源获取

getAttrResId - 获取主题属性资源ID

作用:根据主题属性获取对应的资源ID

参数

  • context:上下文对象(不能为 null)
  • attrId:主题属性ID(如 R.attr.rc_xxx

返回值:资源ID,如果获取失败则返回 0

示例

Java
// 获取背景资源
int bgResId = IMKitThemeManager.getAttrResId(context, R.attr.rc_common_background_color);
if (bgResId != 0) {
view.setBackgroundResource(bgResId);
}

// 获取颜色资源
int colorResId = IMKitThemeManager.getAttrResId(context, R.attr.rc_text_primary_color);
if (colorResId != 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
textView.setTextColor(getResources().getColor(colorResId, context.getTheme()));
} else {
textView.setTextColor(getResources().getColor(colorResId));
}
}

// 获取图标资源
int iconResId = IMKitThemeManager.getAttrResId(context, R.attr.rc_navigation_bar_btn_back_img);
if (iconResId != 0) {
imageView.setImageResource(iconResId);
}

注意事项

  • 返回值为 0 表示获取失败,使用前需要进行判断
  • 该方法会自动根据当前主题和深浅色模式返回对应的资源ID
  • 支持 ContextThemeWrapper 类型的 Context

主题资源说明

目录结构

欢快主题的资源包结构如下:

text
res-lively/                         # 通用资源
├── drawable/ # 通用形状、背景 drawable
├── drawable-xxhdpi/ # 通用图标(PNG)
└── layout/ # 布局文件

res-lively-light/ # 浅色主题专属资源
├── values/
│ ├── lively_light_colors.xml # 浅色主题颜色定义
│ └── lively_light_style.xml # 浅色主题样式定义
├── drawable/ # 浅色特定 drawable
└── drawable-xxhdpi/ # 浅色特定图标

res-lively-dark/ # 深色主题专属资源
├── values/
│ ├── lively_dark_colors.xml # 深色主题颜色定义
│ └── lively_dark_style.xml # 深色主题样式定义
├── drawable/ # 深色特定 drawable
└── drawable-xxhdpi/ # 深色特定图标

样式配置文件

样式配置文件是主题的核心配置,包含颜色和图片的映射关系。

配置文件结构

xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 自定义欢快主题 -->
<style name="RCLivelyLightTheme">
<!-- 主色调 -->
<item name="rc_primary_color">@color/rc_primary_color_lively_light</item>

<!-- 文字色 -->
<item name="rc_text_primary_color">@color/rc_text_primary_color_light</item>
<item name="rc_text_secondary_color">@color/rc_text_secondary_color_light</item>

<!-- 背景颜色 -->
<item name="rc_common_background_color">@color/rc_common_background_color_light</item>

<!-- 图片资源 -->
<item name="rc_navigation_bar_btn_back_img">@drawable/rc_lively_back_light</item>
<item name="rc_navigation_bar_btn_more_img">@drawable/rc_lively_more_light</item>

<!-- 更多配置... -->
</style>
</resources>

字段说明

颜色配置
  • 类型:Color Resource Reference
  • 必填:否
  • 说明:颜色资源引用映射表
  • :颜色属性标识符(如 rc_primary_color
  • :颜色资源引用(如 @color/rc_primary_color_lively_light

颜色值格式

  • #RRGGBB:6 位十六进制,不带透明度(如 #0047FF
  • #RRGGBBAA:8 位十六进制,带透明度(如 #0047FF80
图片配置
  • 类型:Drawable Resource Reference
  • 必填:否
  • 说明:图片资源引用映射表
  • :图片属性标识符(如 rc_icon_back
  • :图片资源引用(如 @drawable/rc_icon_back_lively

图片文件命名规范

  • 支持不同密度的资源文件夹
  • 示例:drawable-mdpi/drawable-hdpi/drawable-xhdpi/drawable-xxhdpi/

颜色配置说明

常用颜色属性

以下是 IMKit 中常用的颜色属性及其用途:

主色调

颜色属性说明使用场景
rc_primary_color主色调按钮、链接、强调文本
rc_secondary_color辅助色次要按钮、辅助信息

文本颜色

颜色属性说明使用场景
rc_text_primary_color主要文本颜色标题、正文
rc_text_secondary_color次要文本颜色副标题、说明文字

背景颜色

颜色属性说明使用场景
rc_common_background_color通用背景颜色页面背景
rc_auxiliary_background_1_color辅助背景颜色 1卡片背景
rc_auxiliary_background_2_color辅助背景颜色 2次级卡片背景
rc_line_background_color分割线颜色列表分割线、边框
rc_conversation_list_background_color会话列表背景色会话列表页面背景
rc_view_background_color视图背景色通用视图背景

功能颜色

颜色属性说明使用场景
rc_success_color成功状态颜色成功提示、确认按钮
rc_hint_color提示颜色提示信息、占位符
rc_disabled_color禁用状态颜色禁用按钮、不可用文本
rc_destruct_color销毁颜色删除、警告操作
rc_link_color链接颜色超链接文本

颜色值格式

支持的格式

  1. 6 位十六进制(RGB)

    #RRGGBB
    示例:#0047FF(蓝色)
  2. 8 位十六进制(RGBA)

    #RRGGBBAA
    示例:#0047FF80(半透明蓝色)

透明度说明

透明度(Alpha)值范围:00(完全透明)到 FF(完全不透明)

常用透明度值:

  • FF:100% 不透明
  • CC:80% 不透明
  • 99:60% 不透明
  • 66:40% 不透明
  • 33:20% 不透明
  • 00:完全透明

示例

xml
<color name="rc_text_primary">#000000</color>      <!-- 纯黑色 -->
<color name="rc_text_secondary">#00000099</color> <!-- 60% 透明度的黑色 -->

关键页面说明

会话列表页面

会话列表页面是应用的主要入口,展示所有会话。

页面效果

会话列表页面

会话列表可定制元素

颜色属性
元素属性说明
页面背景rc_conversation_list_background_color列表背景色
会话标题rc_text_primary_color会话名称
最后消息rc_text_secondary_color最后一条消息内容
时间戳rc_text_secondary_color消息时间
未读数气泡rc_primary_color未读消息数背景
分割线rc_line_background_color会话之间的分割线
图片属性
元素属性说明
默认头像rc_conversation_list_cell_portrait_msg_img单聊默认头像
群组头像rc_conversation_list_cell_group_portrait_img群聊默认头像
置顶图标rc_conversation_list_cell_pin_img置顶标识
免打扰图标rc_conversation_list_cell_block_notification_img免打扰标识

代码示例

Java
// 自定义会话列表背景色
int bgResId = IMKitThemeManager.getAttrResId(context, R.attr.rc_conversation_list_background_color);
if (bgResId != 0) {
listView.setBackgroundResource(bgResId);
}

// 自定义会话标题颜色
int titleColorResId = IMKitThemeManager.getAttrResId(context, R.attr.rc_text_primary_color);
if (titleColorResId != 0) {
titleTextView.setTextColor(getResources().getColor(titleColorResId));
}

会话页面

会话页面是用户进行聊天的核心界面。

页面效果

会话页面

会话页面可定制元素

输入栏

颜色属性:

元素属性说明
输入框背景rc_auxiliary_background_1_color输入框背景色
输入框文字rc_text_primary_color输入文字颜色

图片属性:

元素属性说明
添加按钮rc_conversation_input_bar_add_img添加功能按钮
表情按钮rc_conversation_input_bar_emoji_img表情功能按钮
语音按钮rc_conversation_input_bar_voice_img语音功能按钮
相机按钮rc_conversation_plugin_item_sight_img相机功能按钮
位置按钮rc_conversation_plugin_item_location_img位置功能按钮
图片按钮rc_conversation_plugin_item_image_img图片功能按钮
文件按钮rc_conversation_plugin_item_file_img文件功能按钮
消息气泡

颜色属性:

元素属性说明
发送消息文字rc_text_primary_color自己发送的消息文字
接收消息文字rc_text_primary_color接收的消息文字
消息时间rc_text_secondary_color消息时间戳
链接rc_link_color链接颜色

图片属性:

元素属性说明
发送消息气泡rc_conversation_msg_send_background自己发送的消息背景
接收消息气泡rc_conversation_msg_receiver_background接收的消息背景
消息操作

图片属性:

元素属性说明
复制图标rc_conversation_menu_item_copy_img复制功能
删除图标rc_conversation_menu_item_delete_img消息删除功能
引用图标rc_conversation_menu_item_reference_img消息引用
转发图标rc_conversation_menu_item_forward_img消息转发
多选图标rc_conversation_menu_item_multiple_img消息多选
撤回图标rc_conversation_menu_item_recall_img消息撤回
编辑图标rc_conversation_menu_item_edit_img消息编辑
翻译图标rc_conversation_menu_item_translation_img消息翻译

会话页面代码示例

Java
// 自定义输入框背景
int inputBgResId = IMKitThemeManager.getAttrResId(context, R.attr.rc_auxiliary_background_1_color);
if (inputBgResId != 0) {
inputEditText.setBackgroundResource(inputBgResId);
}

// 自定义添加按钮图标
int addIconResId = IMKitThemeManager.getAttrResId(context, R.attr.rc_conversation_input_bar_add_img);
if (addIconResId != 0) {
addButton.setImageResource(addIconResId);
}

// 自定义消息文字颜色
int textColorResId = IMKitThemeManager.getAttrResId(context, R.attr.rc_text_primary_color);
if (textColorResId != 0) {
messageTextView.setTextColor(getResources().getColor(textColorResId));
}

深浅色模式适配

重要说明

在部分机型上,系统设置切换深浅色模式后,返回 APP 可能无法及时切换到对应的模式。这是由于系统原因导致,当前 APP 通过系统方法获取的深浅色状态仍然是旧值,需要重启 APP 才能生效。

解决方案(推荐)

如果您的应用使用了 AppCompat 库,建议在 Application 中通过 AppCompatDelegate.setDefaultNightMode(nightMode) 来设置应用的深浅色模式,这样可以保证深浅色模式的及时切换。

Java
import androidx.appcompat.app.AppCompatDelegate;

public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();

// 跟随系统(推荐)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);

// 切换到欢快主题
IMKitThemeManager.changeInnerTheme(this, IMKitThemeManager.LIVELY_THEME);
}
}

常见问题

主题切换后 UI 没有更新?

原因:Activity 没有重建

解决方案:调用 recreate() 重建 Activity

Java
IMKitThemeManager.changeInnerTheme(this, IMKitThemeManager.LIVELY_THEME);
recreate();

自定义主题样式不生效?

原因

  • 资源文件夹未在 build.gradle 中正确配置
  • 样式中缺少必要的主题属性
  • ❌ 直接使用了颜色值而不是颜色资源引用

解决方案

  • 检查 build.gradlesourceSets 配置
  • 确保样式中定义了所有必要的主题属性
  • ⚠️ 必须使用 @color/xxx 引用颜色资源,不要直接使用 #RRGGBB 颜色值

系统深浅色切换不及时?

原因:部分机型的系统深浅色状态更新延迟

解决方案:使用 AppCompatDelegate.setDefaultNightMode() 方法(推荐)

Java
// 在 Application onCreate 中设置
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);