自定义会话列表 UI
更新时间: 2026/08/13 16:43:29
功能描述
网易云信 IM UIKit 支持本地和云端会话组件,提供会话列表界面 UI 的自定义配置项,助您快速实现该界面的 UI 个性化定制。
会话列表模块提供以下两种方式对会话列表的 UI 进行个性化定制。
- 通过接口配置的方式自定义 UI。
- 通过源码修改的方式自定义 UI。
如果接口中的配置项满足您的界面个性化需求,请优先使用接口配置方式。
- Swift&Objective-C 通过本地会话组件(
NELocalConversationUIKit)和云端会话组件(NEConversationUIKit)实现。 - SwiftUI 版通过
NEConversationUIKitSwiftUI提供同一套会话列表界面。本地会话和云端会话共用ConversationListView,创建ConversationListViewModel时分别传入.local和.cloud选择数据源。
SwiftUI 配置需要在创建 ConversationListViewModel 前完成。ConversationSwiftUIConfig.mode 当前不用于选择数据源,请以 ConversationListViewModel(mode:) 的 mode 参数为准。
自定义功能描述
UI 元素自定义
Swift&Objective-C 配置项
会话列表界面可自定义的 UI 元素包括但不限于下图中的标注项。
LocalConversationUIConfig | ConversationUIConfig 是整个会话列表的配置文件,其中 UI 实例化对象类型为 LocalConversationUIConfig | ConversationUIConfig。
您可以通过 LocalConversationUIConfig | ConversationUIConfig 类中的个性化配置项,对会话列表的 UI 样式进行修改,个性化配置项具体如下:
| 属性 | 类型 | 说明 |
|---|---|---|
showTitleBar |
Bool | 是否展示界面顶部的标题栏,具体自定义示例见下文的 隐藏标题栏。 |
showTitleBarLeftIcon |
Bool | 是否展示标题栏左侧图标。 |
showTitleBarRightIcon |
Bool | 是否展示标题栏最右侧图标。 |
showTitleBarRight2Icon |
Bool | 是否展示标题栏次最右侧图标。 |
titleBarLeftRes |
UIImage | 标题栏左侧图标。 |
titleBarRightRes |
UIImage | 标题栏最右侧图标。 |
titleBarRight2Res |
UIImage | 标题栏次最右侧图标。 |
titleBarTitle |
String | 标题栏的文案。 |
titleBarTitleColor |
UIColor | 标题栏的颜色值。 |
titleBarRightClick |
() -> Void | 标题栏最右侧按钮点击事件。 |
titleBarRight2Click |
() -> Void | 标题栏次最右侧按钮点击事件。 |
titleBarLeftClick |
() -> Void | 标题栏左侧按钮点击事件。 |
conversationProperties |
会话列表页面的 UI 个性化定制,具体配置见下文。 | |
stickTopButtonTitle |
String | 会话列表 cell 左划置顶按钮文案内容。 |
stickTopButtonCancelTitle |
String | 会话列表 cell 左划取消置顶按钮文案内容。 |
stickTopButtonBackgroundColor |
UIColor | 会话列表 cell 左划置顶按钮背景颜色。 |
stickTopButtonClick |
会话列表 cell 左划置顶按钮点击事件。 | |
deleteButtonTitle |
String | 会话列表 cell 左划删除按钮文案内容。 |
deleteButtonBackgroundColor |
UIColor | 会话列表 cell 左划删除按钮背景颜色。 |
deleteButtonClick |
会话列表 cell 左划删除按钮点击事件。 | |
itemClick |
会话列表点击事件,包括单击和长按事件。 | |
customController |
自定义界面 UI 接口,回调中会传入会话列表界面的UI布局,您可以进行UI元素调整。 |
LocalConversationProperties | ConversationProperties 类的个性化配置项具体如下:
| 属性 | 类型 | 说明 |
|---|---|---|
itemTitleColor |
UIColor | 会话标题的字体颜色,具体示例见下文的 修改会话名称字体颜色和大小。 |
itemTitleSize |
CGFloat | 会话标题的字体大小,具体示例见下文的 修改会话名称字体颜色和大小。 |
itemBackground |
UIColor | 未被置顶的会话项的背景色。 |
itemStickTopBackground |
UIColor | 置顶的会话项的背景色。 |
itemContentColor |
UIColor | 会话消息缩略内容的字体颜色。 |
itemContentSize |
CGFloat | 会话消息缩略内容的字体大小。 |
itemDateColor |
UIColor | 会话时间的字体颜色。 |
itemDateSize |
CGFloat | 会话时间的字体大小。 |
avatarType |
头像类型,rectangle = 1 为矩形,cycle 为圆形。 |
|
avatarCornerRadius |
CGFloat | 头像圆角大小,仅在 avatarType = rectangle 时有效。 |
SwiftUI 配置项
SwiftUI 版通过 ConversationSwiftUIConfig 配置会话列表功能和事件,主要配置项如下:
| 属性 | 类型 | 说明 |
|---|---|---|
styleMode |
ConversationStyleMode |
会话列表样式,可选 .normal 或 .fun。 |
mode |
ConversationMode? |
保留的模式字段。当前数据源仍需通过 ConversationListViewModel(mode:) 选择。 |
title |
String? |
标题栏文案。 |
showTitleBar |
Bool |
是否显示标题栏。 |
showTitleBarLeftIcon |
Bool |
是否显示标题栏左侧品牌图标。 |
showTitleBarRightIcon |
Bool |
是否显示标题栏右侧新增按钮。 |
showTitleBarSearchIcon |
Bool |
是否显示普通样式标题栏中的搜索按钮。 |
showScanQREntry |
Bool |
是否在更多操作菜单中显示扫一扫入口。 |
themeToken |
ConversationThemeToken |
会话列表主题配置。 |
routeHandler |
((ConversationRouteContext) -> Void)? |
监听会话路由信息,不替代组件内置的聊天路由。 |
actionHandler |
((ConversationAction) -> Void)? |
处理添加好友、加入群组、创建讨论组、创建高级群和扫一扫事件。 |
searchHandler |
(() -> Void)? |
处理搜索入口点击事件。未设置时使用组件内置搜索页面。 |
qrScanHandler |
(() -> Void)? |
处理扫一扫事件。设置 actionHandler 后,扫一扫也由 actionHandler 处理。 |
bodyTopContentProvider |
((ConversationBodyTopContentContext) -> AnyView?)? |
在会话列表内容顶部插入自定义 SwiftUI 视图。 |
onToast |
((String) -> Void)? |
接收会话组件产生的提示文案。 |
ConversationThemeToken 用于配置 SwiftUI 会话列表的颜色和尺寸,当前界面使用的配置项如下:
| 属性 | 类型 | 说明 |
|---|---|---|
pageBackground |
Color |
页面背景色。 |
navigationBackground |
Color |
标题栏背景色。 |
rowBackground |
Color |
普通会话行背景色。 |
rowStickTopBackground |
Color |
置顶会话行背景色。 |
rowSeparatorColor |
Color |
会话行分隔线颜色。 |
primaryTextColor |
Color |
会话名称和标题栏标题颜色。 |
secondaryTextColor |
Color |
会话消息摘要颜色。 |
tertiaryTextColor |
Color |
会话时间等辅助文字颜色。 |
accentColor |
Color |
搜索结果高亮等强调内容的颜色。 |
destructiveColor |
Color |
左滑删除按钮背景色。 |
topActionColor |
Color |
左滑置顶或取消置顶按钮背景色。 |
unreadBackgroundColor |
Color |
未读数背景色。 |
unreadTextColor |
Color |
未读数文字颜色。 |
atTextColor |
Color |
被 @ 提醒文案颜色。 |
onlineColor |
Color |
在线状态标记颜色。 |
offlineColor |
Color |
离线状态标记颜色。 |
networkBrokenBackground |
Color |
网络异常提示背景色。 |
networkBrokenTitleColor |
Color |
网络异常提示文字颜色。 |
popoverBackground |
Color |
更多操作菜单背景色。 |
popoverTextColor |
Color |
更多操作菜单文字颜色。 |
searchBackground |
Color |
搜索入口和搜索界面背景色。 |
rowHeight |
CGFloat |
会话行高度。 |
rowHorizontalPadding |
CGFloat |
会话行水平内边距。 |
avatarSize |
CGFloat |
头像尺寸。 |
avatarCornerRadius |
CGFloat |
头像圆角。 |
titleFontSize |
CGFloat |
会话名称字体大小。 |
subtitleFontSize |
CGFloat |
会话消息摘要字体大小。 |
timeFontSize |
CGFloat |
会话时间字体大小。 |
unreadMinHeight |
CGFloat |
未读数视图最小高度。 |
unreadHorizontalPadding |
CGFloat |
未读数视图水平内边距。 |
onlineIndicatorSize |
CGFloat |
在线状态标记尺寸。 |
popoverItemHeight |
CGFloat |
更多操作菜单单项高度。 |
searchRowHeight |
CGFloat |
搜索结果行高度。 |
showsRowSeparator |
Bool |
是否显示会话行分隔线。 |
界面布局自定义
Swift&Objective-C 配置项
除了界面的 UI 元素,您也可对界面的布局进行自定义,NELocalConversationUIKit | NEConversationUIKit 模块中的 LocalConversationListCell | ConversationListCell 支持对会话列表界面布局进行调整,包括界面元素调整和界面背景修改等。会话列表界面的默认视图布局如下图所示。
该界面各视图的说明如下:
| 属性 | 类型 | 说明 |
|---|---|---|
titleBarView |
UIView | 会话列表界面标题视图,可通过 navigationView 来获取视图进行样式修改。 |
navigationView |
TabNavigationView | 会话列表界面的标题视图,可在子类直接获取视图进行样式修改,具体自定义示例请参见下文的 自定义标题栏。 |
bodyTopView |
UIView | 会话列表上方的小块视图,可在子类直接获取视图进行样式修改。可用于在会话列表和顶部的界面标题中间增加新的 UI 元素。 |
bodyView |
UIView | 会话列表界面的内容视图,可在子类直接获取视图进行样式修改。布局中包含 brokenNetworkView 错误提示视图和 contentView 列表视图。 |
brokenNetworkView |
NEBrokenNetworkView | 会话列表界面错误提示视图,可在子类直接获取视图进行样式修改。 |
contentView |
UIView | 会话列表界面的列表视图,可在子类直接获取视图进行样式修改。布局中包含 tableView 列表和 emptyView 空数据提示视图。 |
tableView |
UITableView | 会话列表界面的列表,可在子类直接获取视图进行样式修改。 |
emptyView |
NEEmptyDataView | 会话列表界面空数据提示视图,可在子类直接获取视图进行样式修改。 |
bodyBottomView |
UIView | 会话列表底部的小块视图,可在子类直接获取视图进行样式修改,用于在会话列表底部增加新的 UI 元素。 |
SwiftUI 配置项
SwiftUI 版使用视图组合构建会话列表,主要视图和自定义方式如下:
| 视图 | 说明 | 自定义方式 |
|---|---|---|
ConversationListView |
会话列表根视图。 | 公开视图,可传入 ConversationListViewModel 和 ConversationThemeToken。 |
ConversationHeaderView |
标题栏。 | 通过 ConversationSwiftUIConfig 配置文案和显隐;替换图标或结构需修改源码。 |
bodyTopContentProvider |
标题栏与列表内容之间的顶部扩展区域。 | 通过 ConversationSwiftUIConfig 插入 SwiftUI 视图。 |
ConversationNetworkBannerView |
网络异常提示视图。 | 通过 ConversationThemeToken 修改颜色;替换结构需修改源码。 |
ConversationRowView |
会话行。 | 通过 ConversationThemeToken 修改样式;调整布局或增加元素需修改源码。 |
ConversationSwipeRow |
会话行左滑容器。 | 通过 ConversationThemeToken 修改颜色;修改文案或操作需修改源码。 |
ConversationActionMenuView |
更多操作菜单。 | 通过 actionHandler 处理事件,通过 showScanQREntry 控制扫一扫入口;修改菜单结构需修改源码。 |
除 ConversationListView 外,上表中的具体视图类型均为组件内部实现,不是公开的视图 API。SwiftUI 版当前未提供空页面、底部扩展视图或会话行的 View Provider。
通过配置项自定义 UI 示例
会话列表的个性化 UI 样式需要在会话列表界面加载之前配置,您可以在 didFinishLaunchingWithOptions 方法中设置个性化定制属性。
SwiftUI 版可在应用初始化阶段调用 NEConversationUIKitSwiftUIClient.shared.setup(config:)。已经创建的 ConversationListViewModel 会保留创建时的配置,更新配置后需要重新创建 ViewModel 和页面。
SwiftUI 版切换内置普通样式和娱乐样式时,应同时更新 styleMode 和 themeToken:
Swiftimport NEConversationUIKitSwiftUI
var config = ConversationSwiftUIConfigCenter.shared.current()
config = config.resolvingStyle(.fun)
NEConversationUIKitSwiftUIClient.shared.updateConfig(config)
隐藏标题栏
-
示例代码
本地会话Swift:
SwiftLocalConversationUIConfig.shared.ui.showTitleBar = falseObjective-C:
Objective-CLocalConversationUIConfig.shared.ui.showTitleBar = NO;SwiftUI:
Swiftimport NEConversationUIKitSwiftUI var config = ConversationSwiftUIConfig() config.showTitleBar = false NEConversationUIKitSwiftUIClient.shared.setup(config: config)云端会话Swift:
SwiftConversationUIConfig.shared.ui.showTitleBar = falseObjective-C:
Objective-CConversationUIConfig.shared.ui.showTitleBar = NO;SwiftUI:
Swiftimport NEConversationUIKitSwiftUI var config = ConversationSwiftUIConfig() config.showTitleBar = false NEConversationUIKitSwiftUIClient.shared.setup(config: config)除此之外,还可以隐藏标题栏中的新增图标和搜索图标。详见上文的个性化配置项列表。
-
效果对比
默认 自定义后 

修改会话名称字体颜色和大小
-
示例代码
本地会话Swift:
Swift// 会话名称字体大小 LocalConversationUIConfig.shared.ui.conversationProperties.itemTitleSize = 24 // 会话名称字体颜色 LocalConversationUIConfig.shared.ui.conversationProperties.itemTitleColor = UIColor.redObjective-C:
Objective-C// 会话名称字体大小 LocalConversationUIConfig.shared.ui.conversationProperties.itemTitleSize = 24; // 会话名称字体颜色 LocalConversationUIConfig.shared.ui.conversationProperties.itemTitleColor = [UIColor redColor];SwiftUI:
Swiftimport NEConversationUIKitSwiftUI import SwiftUI var config = ConversationSwiftUIConfig() config.themeToken.titleFontSize = 24 config.themeToken.primaryTextColor = .red NEConversationUIKitSwiftUIClient.shared.setup(config: config)云端会话Swift:
Swift// 会话名称字体大小 ConversationUIConfig.shared.ui.conversationProperties.itemTitleSize = 24 // 会话名称字体颜色 ConversationUIConfig.shared.ui.conversationProperties.itemTitleColor = UIColor.redObjective-C:
Objective-C// 会话名称字体大小 ConversationUIConfig.shared.ui.conversationProperties.itemTitleSize = 24; // 会话名称字体颜色 ConversationUIConfig.shared.ui.conversationProperties.itemTitleColor = [UIColor redColor];SwiftUI:
Swiftimport NEConversationUIKitSwiftUI import SwiftUI var config = ConversationSwiftUIConfig() config.themeToken.titleFontSize = 24 config.themeToken.primaryTextColor = .red NEConversationUIKitSwiftUIClient.shared.setup(config: config)除此之外,还可以修改会话中的副标题和时间的字体颜色、字体大小,详见上文的个性化配置项列表。
-
效果对比
默认 自定义后 

通过源码自定义 UI 示例
NEBaseLocalConversationController 为本地会话列表的实现类,内部包含本地会话相关的回调,具体如下:
Swift// MARK: ================= LocalConversationViewModelDelegate===================
extension NEBaseLocalConversationController: LocalConversationViewModelDelegate {
open func reloadData() {
delegate?.onDataLoaded()
}
/// 带排序的刷新
open func reloadTableView() {
if viewModel.stickTopConversations.count <= 0, viewModel.conversationListData.count <= 0 {
emptyView.isHidden = false
} else {
emptyView.isHidden = true
}
viewModel.conversationListData.sort()
viewModel.stickTopConversations.sort()
tableView.reloadData()
}
/// 由于数据变更可能导致底部有更多数据,此方法重新使列表加载更多能力开启
public func loadMoreStateChange(_ finish: Bool) {
if finish {
tableView.mj_footer = nil
} else {
tableView.mj_footer = MJRefreshBackNormalFooter(
refreshingTarget: self,
refreshingAction: #selector(loadMoreData)
)
}
}
}
NEBaseConversationController 为云端会话列表的实现类,内部包含云端会话相关的回调,具体如下:
Swift// MARK: ================= ConversationViewModelDelegate===================
extension NEBaseConversationController: ConversationViewModelDelegate {
open func reloadData() {
delegate?.onDataLoaded()
}
/// 带排序的刷新
open func reloadTableView() {
if viewModel.stickTopConversations.count <= 0, viewModel.conversationListData.count <= 0 {
emptyView.isHidden = false
} else {
emptyView.isHidden = true
}
viewModel.conversationListData.sort()
viewModel.stickTopConversations.sort()
tableView.reloadData()
}
/// 由于数据变更可能导致底部有更多数据,此方法重新使列表加载更多能力开启
public func loadMoreStateChange(_ finish: Bool) {
if finish {
tableView.mj_footer = nil
} else {
tableView.mj_footer = MJRefreshBackNormalFooter(
refreshingTarget: self,
refreshingAction: #selector(loadMoreData)
)
}
}
}
SwiftUI 版的列表加载、排序、分页、置顶和删除流程由 ConversationListViewModel 及 LocalConversationDataSource、CloudConversationDataSource 实现。当前未公开自定义数据源注入和 onDataLoaded 回调;如需修改这些流程,请以源码方式接入并修改上述实现。
其他
-
Swift&Objective-C 组件
自定义配置 说明 修改会话列表右侧按钮点击事件 通过 TabNavigationViewDelegate协议中的searchAction和didClickAddBtn方法进行修改。构造更多弹窗中的选项内容 通过 NEBasePopListView视图类构造,当前默认设置为添加好友、创建讨论组、创建高级群。实现长按置顶会话和删除会话弹窗 请参见 NEBaseLocalConversationController/NEBaseConversationController中UITableview中的代理方法。 -
SwiftUI 组件
自定义配置 说明 修改搜索和新增菜单事件 分别通过 searchHandler和actionHandler处理。控制扫一扫入口 通过 showScanQREntry控制显隐,通过actionHandler或qrScanHandler处理事件。修改更多菜单结构 当前没有公开配置项,需要修改 ConversationActionMenuView.swift。修改左滑置顶和删除操作 当前仅支持通过 ConversationThemeToken修改颜色;文案和行为需要修改ConversationListView.swift中的ConversationSwipeRow和ConversationListViewModel.swift。
自定义单元格(TableviewCell)
Swift
用户可自定义云端会话列表单元格,实现数据的自定义展示。
实现步骤与示例代码:
- 继承
LocalConversationListCell类,实现自定义单元格,对数据进行展示。
Swiftopen class CustomLocalConversationListCell: LocalConversationListCell {
// 新增 UI 元素,用于展示在线状态
private lazy var onlineView: UIImageView = {
let notify = UIImageView()
notify.translatesAutoresizingMaskIntoConstraints = false
notify.image = UIImage(named: "about_yunxin")
return notify
}()
override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// 头像右下角
contentView.addSubview(onlineView)
NSLayoutConstraint.activate([
onlineView.rightAnchor.constraint(equalTo: headImge.rightAnchor),
onlineView.bottomAnchor.constraint(equalTo: headImge.bottomAnchor),
onlineView.widthAnchor.constraint(equalToConstant: 12),
onlineView.heightAnchor.constraint(equalToConstant: 12),
])
}
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// 此方法用于数据和 UI 的绑定,可在此处在数据展示前对数据进行处理
open func configureData(_ sessionModel: NELocalConversationListModel?) {
super.configureData(sessionModel)
// subTitle.text = "[自定义类型文案]"
}
}
- 继承
LocalConversationController类,实现自定义表格(以通用皮肤为例)。
Swiftopen class CustomLocalConversationController: LocalConversationController, NEBaseLocalConversationControllerDelegate {
override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
delegate = self
// 自定义 cell, [NELocalConversationListModel.customType: 需要注册的自定义 UI 类型]
// 自定义 cell 的注册字典需要在 viewDidLoad 之前完成初始化
cellRegisterDic[1] = CustomLocalConversationListCell.self
}
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override open func viewDidLoad() {
super.viewDidLoad()
}
override open func deleteActionHandler(action: UITableViewRowAction, indexPath: IndexPath) {
showSingleAlert(message: "override deleteActionHandler") {}
}
override open func topActionHandler(action: UITableViewRowAction, indexPath: IndexPath, isTop: Bool) {
showSingleAlert(message: "override topActionHandler") {
super.topActionHandler(action: action, indexPath: indexPath, isTop: isTop)
}
}
// 父类加载完数据后会调用此方法,可在此对数据进行二次处理
public func onDataLoaded() {
guard let conversationList = viewModel.conversationListArray else { return
}
conversationList.forEach { model in
model.customType = 1
}
tableView.reloadData()
}
}
注意: onDataLoaded 方法调用时,表明父类已完成数据的加载,数据存放在 viewModel.conversationListArray 列表中,数据模型定义如下:
Swift/*
本地会话列表数据模型 NELocalConversationListModel
// customType: 自定义 UI 类型,其在注册本地会话列表 cell 时作为 key 与自定义 cell 进行绑定
// localExtension: 本地扩展字段,可根据业务需求添加数据,与 customType 结合可实现多种自定义 cell 的展示
*/
@objcMembers
public class NELocalConversationListModel: NSObject, Comparable {
/// 会话
public var conversation: V2NIMLocalConversation?
/// 自定义类型
public var customType = 0
}
需要在 viewDidLoad 之前完成本地会话列表 cell 注册字典(cellRegisterDic)的初始化,cellRegisterDic 的类型为 [Int : NEBaseLocalConversationListCell.Type],其中 key 对应本地会话列表数据模型中的 customType,需要在此处与其对应的自定义 UI 类型进行绑定,从而实现不同类型的自定义单元格的对应展示。
例如在用户头像下 添加小标,如下图所示:
| 默认 | 自定义后 |
|---|---|
![]() |
![]() |
:::
- 继承
ConversationListCell类,实现自定义单元格,对数据进行展示。
Swiftopen class CustomConversationListCell: ConversationListCell {
// 新增 UI 元素,用于展示在线状态
private lazy var onlineView: UIImageView = {
let notify = UIImageView()
notify.translatesAutoresizingMaskIntoConstraints = false
notify.image = UIImage(named: "about_yunxin")
return notify
}()
override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// 头像右下角
contentView.addSubview(onlineView)
NSLayoutConstraint.activate([
onlineView.rightAnchor.constraint(equalTo: headImge.rightAnchor),
onlineView.bottomAnchor.constraint(equalTo: headImge.bottomAnchor),
onlineView.widthAnchor.constraint(equalToConstant: 12),
onlineView.heightAnchor.constraint(equalToConstant: 12),
])
}
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// 此方法用于数据和 UI 的绑定,可在此处在数据展示前对数据进行处理
open func configureData(_ sessionModel: NEConversationListModel?) {
super.configureData(sessionModel)
// subTitle.text = "[自定义类型文案]"
}
}
- 继承
ConversationController类,实现自定义表格(以通用皮肤为例)。
Swiftopen class CustomConversationController: ConversationController, NEBaseConversationControllerDelegate {
override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
delegate = self
// 自定义 cell, [NEConversationListModel.customType: 需要注册的自定义 UI 类型]
// 自定义 cell 的注册字典需要在 viewDidLoad 之前完成初始化
cellRegisterDic[1] = CustomConversationListCell.self
}
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override open func viewDidLoad() {
super.viewDidLoad()
}
override open func deleteActionHandler(action: UITableViewRowAction, indexPath: IndexPath) {
showSingleAlert(message: "override deleteActionHandler") {}
}
override open func topActionHandler(action: UITableViewRowAction, indexPath: IndexPath, isTop: Bool) {
showSingleAlert(message: "override topActionHandler") {
super.topActionHandler(action: action, indexPath: indexPath, isTop: isTop)
}
}
// 父类加载完数据后会调用此方法,可在此对数据进行二次处理
public func onDataLoaded() {
guard let conversationList = viewModel.conversationListArray else { return
}
conversationList.forEach { model in
model.customType = 1
}
tableView.reloadData()
}
}
注意: onDataLoaded 方法调用时,表明父类已完成数据的加载,数据存放在 viewModel.conversationListArray 列表中,数据模型定义如下:
swift/*
云端会话列表数据模型 NEConversationListModel
// customType: 自定义 UI 类型,其在注册云端会话列表 cell 时作为 key 与自定义 cell 进行绑定
// localExtension: 本地扩展字段,可根据业务需求添加数据,与 customType 结合可实现多种自定义 cell 的展示
*/
@objcMembers
public class NEConversationListModel: NSObject, Comparable {
/// 会话
public var conversation: V2NIMConversation?
/// 自定义类型
public var customType = 0
}
需要在 viewDidLoad 之前完成云端会话列表 cell 注册字典(cellRegisterDic)的初始化,cellRegisterDic 的类型为 [Int : NEBaseConversationListCell.Type],其中 key 对应云端会话列表数据模型中的 customType,需要在此处与其对应的自定义 UI 类型进行绑定,从而实现不同类型的自定义单元格的对应展示。
例如在用户头像下 添加小标,如下图所示:
| 默认 | 自定义后 |
|---|---|
![]() |
![]() |
:::
SwiftUI
SwiftUI 版当前没有公开会话行 View Provider、Cell 注册字典或 onDataLoaded 回调,不能通过配置替换单个会话行。如需在头像附近增加任意小标或调整会话行布局,请以源码方式接入并修改 ConversationRowView.swift。
如果仅需展示组件已支持的在线状态标记,可直接启用在线状态:
Swiftimport NEChatKit
IMKitConfigCenter.shared.enableOnlineStatus = true
自定义标题栏(navigationView)
效果对比:
| 默认 | 自定义后 |
|---|---|
![]() |
![]() |
Swift
Swiftopen class CustomLocalConversationController: LocalConversationController {
override public func viewDidLoad() {
// 实现协议(重写 tabbar 点击事件)
navigationView.delegate = self
// 自定义本地会话列表标题、图标、间距
navigationView.brandBtn.setTitle("消息", for: .normal)
navigationView.brandBtn.setImage(nil, for: .normal)
navigationView.brandBtn.layoutButtonImage(style: .left, space: 0)
// 自定义添加按钮图标
navigationView.addBtn.setImage(UIImage.ne_imageNamed(name: "noNeed_notify"), for: .normal)
...
super.viewDidLoad()
}
// 通过继承方式重写次最右侧按钮点击事件, 这种方式会覆盖配置项中的点击事件
override open func searchAction() {
// searchAction
}
// 通过继承方式重写最右侧按钮点击事件, 这种方式会覆盖配置项中的点击事件
override open func didClickAddBtn() {
showSingleAlert(message: "override didClickAddBtn") {
// didClickAddBtn
}
}
}
Swiftopen class CustomConversationController: ConversationController {
override public func viewDidLoad() {
// 实现协议(重写 tabbar 点击事件)
navigationView.delegate = self
// 自定义云端会话列表标题、图标、间距
navigationView.brandBtn.setTitle("消息", for: .normal)
navigationView.brandBtn.setImage(nil, for: .normal)
navigationView.brandBtn.layoutButtonImage(style: .left, space: 0)
// 自定义添加按钮图标
navigationView.addBtn.setImage(UIImage.ne_imageNamed(name: "noNeed_notify"), for: .normal)
...
super.viewDidLoad()
}
// 通过继承方式重写次最右侧按钮点击事件, 这种方式会覆盖配置项中的点击事件
override open func searchAction() {
// searchAction
}
// 通过继承方式重写最右侧按钮点击事件, 这种方式会覆盖配置项中的点击事件
override open func didClickAddBtn() {
showSingleAlert(message: "override didClickAddBtn") {
// didClickAddBtn
}
}
}
上述示例代码中 navigationView 为会话列表页面的标题栏视图,用户可自定义其中的 UI 元素,包括但不限于标题、标题图标、搜索按钮及其点击事件和添加按钮及其点击事件。
SwiftUI
SwiftUI 版可配置标题文案和内置图标的显隐;如需完全替换标题栏,可隐藏内置标题栏后通过视图组合添加业务标题栏。
Swiftimport NEConversationUIKitSwiftUI
import SwiftUI
struct CustomConversationView: View {
@StateObject private var viewModel: ConversationListViewModel
@MainActor
init(mode: ConversationMode) {
var config = ConversationSwiftUIConfigCenter.shared.current()
config.showTitleBar = false
_viewModel = StateObject(
wrappedValue: ConversationListViewModel(mode: mode, config: config)
)
}
var body: some View {
VStack(spacing: 0) {
Text("消息")
ConversationListView(viewModel: viewModel)
}
}
}
会话列表页顶部扩展视图
例如,可以在会话列表顶部增加提示条。
效果对比:
| 默认 | 自定义后 |
|---|---|
![]() |
![]() |
Swift
Swiftpublic class CustomView: UIView {
public let btn = UIButton()
override public init(frame: CGRect) {
super.init(frame: frame)
btn.translatesAutoresizingMaskIntoConstraints = false
btn.addTarget(self, action: #selector(tapView), for: .touchUpInside)
btn.setTitle("按钮", for: .normal)
btn.backgroundColor = .red
addSubview(btn)
NSLayoutConstraint.activate([
btn.topAnchor.constraint(equalTo: topAnchor),
btn.bottomAnchor.constraint(equalTo: bottomAnchor),
btn.widthAnchor.constraint(equalToConstant: 200),
btn.centerXAnchor.constraint(equalTo: centerXAnchor),
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func tapView() {
print("点击了自定义按钮")
}
}
open class CustomLocalConversationController: LocalConversationController {
public lazy var customTopView: CustomView = {
let view = CustomView(frame: CGRect(x: 0, y: 10, width: NEConstant.screenWidth, height: 40))
view.backgroundColor = .blue
return view
}()
override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func viewDidLoad() {
// 顶部 bodyTopView 中添加自定义 view(需要设置 bodyTopView 的高度)
customTopView.btn.setTitle("通过重写方式添加", for: .normal)
bodyTopView.addSubview(customTopView)
bodyTopViewHeight = 80
// 自定义占位图文案、背景图片
emptyView.setEmptyImage(image: UIImage())
emptyView.settingContent(content: "")
...
super.viewDidLoad()
}
// 通过继承方式重写次最右侧按钮点击事件, 这种方式会覆盖配置项中的点击事件
override open func searchAction() {
bodyTopViewHeight = 80
bodyBottomViewHeight = 80
}
// 通过继承方式重写最右侧按钮点击事件, 这种方式会覆盖配置项中的点击事件
override open func didClickAddBtn() {
bodyTopViewHeight = 0
bodyBottomViewHeight = 0
}
}
Swiftpublic class CustomView: UIView {
public let btn = UIButton()
override public init(frame: CGRect) {
super.init(frame: frame)
btn.translatesAutoresizingMaskIntoConstraints = false
btn.addTarget(self, action: #selector(tapView), for: .touchUpInside)
btn.setTitle("按钮", for: .normal)
btn.backgroundColor = .red
addSubview(btn)
NSLayoutConstraint.activate([
btn.topAnchor.constraint(equalTo: topAnchor),
btn.bottomAnchor.constraint(equalTo: bottomAnchor),
btn.widthAnchor.constraint(equalToConstant: 200),
btn.centerXAnchor.constraint(equalTo: centerXAnchor),
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func tapView() {
print("点击了自定义按钮")
}
}
open class CustomConversationController: ConversationController {
public lazy var customTopView: CustomView = {
let view = CustomView(frame: CGRect(x: 0, y: 10, width: NEConstant.screenWidth, height: 40))
view.backgroundColor = .blue
return view
}()
override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
public required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func viewDidLoad() {
// 顶部 bodyTopView 中添加自定义 view(需要设置 bodyTopView 的高度)
customTopView.btn.setTitle("通过重写方式添加", for: .normal)
bodyTopView.addSubview(customTopView)
bodyTopViewHeight = 80
// 自定义占位图文案、背景图片
emptyView.setEmptyImage(image: UIImage())
emptyView.settingContent(content: "")
...
super.viewDidLoad()
}
// 通过继承方式重写次最右侧按钮点击事件, 这种方式会覆盖配置项中的点击事件
override open func searchAction() {
bodyTopViewHeight = 80
bodyBottomViewHeight = 80
}
// 通过继承方式重写最右侧按钮点击事件, 这种方式会覆盖配置项中的点击事件
override open func didClickAddBtn() {
bodyTopViewHeight = 0
bodyBottomViewHeight = 0
}
}
示例代码中 bodyTopView 为会话列表页顶部预留的扩展视图,bodyTopViewHeight 为该扩展视图的高度,更改此变量会刷新页面布局。
SwiftUI
通过 bodyTopContentProvider 添加顶部扩展视图,本地会话和云端会话共用此配置。
Swiftimport NEConversationUIKitSwiftUI
import SwiftUI
var config = ConversationSwiftUIConfigCenter.shared.current()
config.bodyTopContentProvider = { _ in
AnyView(
Button("按钮") {
print("点击了自定义按钮")
}
.frame(maxWidth: .infinity, minHeight: 40)
)
}
NEConversationUIKitSwiftUIClient.shared.updateConfig(config)
SwiftUI 版当前没有公开底部扩展视图和空页面 Provider;如需替换对应区域,需要修改 ConversationListView.swift。







