文档中心>直播 SDK>UI 自定义>调整语聊麦位布局及挂件

调整语聊麦位布局及挂件

最近更新时间:2026-02-27 10:18:07

我的收藏

组件概述

语聊麦位组件SeatGridView)是专门为语音聊天室场景设计的核心 UI 控件。它自动关联麦位状态,支持展示用户信息、音量波纹及房主标识。通过本文档,您可以根据业务需求(例如多人交友、游戏开黑)快速调整麦位布局或完全自定义麦位视图。

准备工作

在开始调整语聊麦位组件前,请先参考 主播开播观众观看 完成主流程的搭建。

设置麦位列表布局

组件内置了多种布局模式,适用于不同的语聊场景。您可以通过 setLayoutMode 接口快速切换,无需手动计算位置。

效果预览

宫格布局
元素布局
纵向布局
自定义布局

















接口说明

Android
iOS
Flutter
Kotlin
fun setLayoutMode(layoutMode: VoiceRoomDefine.LayoutMode, layoutConfig: VoiceRoomDefine.SeatViewLayoutConfig?)
Swift
public func setLayoutMode(layoutMode: SGLayoutMode, layoutConfig: SGSeatViewLayoutConfig? = nil)
void setLayoutMode(LayoutMode layoutMode, SeatWidgetLayoutConfig? layoutConfig);
参数
描述
layoutMode
布局模式:
GRID(宫格布局):适用于多人语聊场景,所有麦位均匀分布。
FOCUS(元素布局):适用于有主麦位的场景,突出显示主麦位。
VERTICAL(纵向布局):适用于竖屏场景,麦位垂直排列。
FREE(自定义布局):适用于需要完全自定义布局的场景 。
layoutConfig
自定义的行列布局信息,仅当 layoutModeFREE 时需传入此参数。

代码示例

您可以通过以下方式快速设置麦位列表布局。
Android
iOS
Flutter
Kotlin
Java
// 设置宫格布局
seatGridView.setLayoutMode(VoiceRoomDefine.LayoutMode.GRID, null)

// 设置元素布局
seatGridView.setLayoutMode(VoiceRoomDefine.LayoutMode.FOCUS, null)

// 设置纵向布局
seatGridView.setLayoutMode(VoiceRoomDefine.LayoutMode.VERTICAL, null)

// 设置自定义布局
val layoutConfig = VoiceRoomDefine.SeatViewLayoutConfig().apply {
rowConfigs = ArrayList()
rowSpacing = dp2px(10); // 每行的间距
}
// 第一行配置
val rowConfig1 = VoiceRoomDefine.SeatViewLayoutRowConfig().apply {
count = 3 // 第一行显示的数量
seatSize = VoiceRoomDefine.Size(dp2px(50), dp2px(50)) // 第一行显示的每个麦位视图大小
seatSpacing = dp2px(10) // 第一行每个麦位的水平间距
alignment = VoiceRoomDefine.SeatViewLayoutRowAlignment.CENTER // 第一行麦位的对齐方式
}
layoutConfig.rowConfigs.add(rowConfig1)
// 第二行配置
val rowConfig2 = VoiceRoomDefine.SeatViewLayoutRowConfig().apply {
count = 3 // 第二行显示的数量
seatSize = VoiceRoomDefine.Size(dp2px(50), dp2px(50)) // 第二行显示的每个麦位大小
seatSpacing = dp2px(10) // 第二行每个麦位的水平间距
alignment = VoiceRoomDefine.SeatViewLayoutRowAlignment.SPACE_AROUND // 第二行麦位的对齐方式
}
layoutConfig.rowConfigs.add(rowConfig2)
seatGridView.setLayoutMode(VoiceRoomDefine.LayoutMode.FREE, layoutConfig)
// 设置宫格布局
seatGridView.setLayoutMode(VoiceRoomDefine.LayoutMode.GRID, null)

// 设置元素布局
seatGridView.setLayoutMode(VoiceRoomDefine.LayoutMode.FOCUS, null)

// 设置纵向布局
seatGridView.setLayoutMode(VoiceRoomDefine.LayoutMode.VERTICAL, null)

// 设置自由布局
VoiceRoomDefine.SeatViewLayoutConfig layoutConfig = new VoiceRoomDefine.SeatViewLayoutConfig();
layoutConfig.rowConfigs = new ArrayList<>();
layoutConfig.rowSpacing = dp2px(10); // 每行的间距
// 第一行配置
VoiceRoomDefine.SeatViewLayoutRowConfig rowConfig1 = new VoiceRoomDefine.SeatViewLayoutRowConfig();
rowConfig1.count = 3; // 第一行显示的数量
rowConfig1.seatSize = new VoiceRoomDefine.Size(dp2px(50),dp2px(50)); // 第一行显示的每个麦位视图大小
rowConfig1.seatSpacing = dp2px(10); // 第一行每个麦位的水平间距
rowConfig1.alignment = VoiceRoomDefine.SeatViewLayoutRowAlignment.CENTER; // 第一行麦位的对齐方式
layoutConfig.rowConfigs.add(rowConfig1);
// 第二行配置
VoiceRoomDefine.SeatViewLayoutRowConfig rowConfig2 = new VoiceRoomDefine.SeatViewLayoutRowConfig();
rowConfig2.count = 3; // 第二行显示的数量
rowConfig2.seatSize = new VoiceRoomDefine.Size(dp2px(50),dp2px(50)); // 第二行显示的每个麦位视图大小
rowConfig2.seatSpacing = dp2px(10); // 第二行每个麦位的水平间距
rowConfig2.alignment = VoiceRoomDefine.SeatViewLayoutRowAlignment.SPACE_AROUND; // 第二行麦位的对齐方式
layoutConfig.rowConfigs.add(rowConfig2);
seatGridView.setLayoutMode(VoiceRoomDefine.LayoutMode.FREE, layoutConfig);
Swift
import LiveStreamCore

// 设置宫格布局
seatGridView.setLayoutMode(layoutMode: .grid)

// 设置元素布局
seatGridView.setLayoutMode(layoutMode: .focus)

// 设置纵向布局
seatGridView.setLayoutMode(layoutMode: .vertical)

// 设置自定义布局
// 第一行配置
let rowConfig1 = SGSeatViewLayoutRowConfig(count: 3, // 第一行显示的数量
seatSpacing: 10, // 第一行每个麦位的水平间距
seatSize: CGSize(width: 50, height: 50), // 第一行显示的每个麦位视图大小
alignment: .center) // 第一行麦位的对齐方式
// 第二行配置
let rowConfig2 = SGSeatViewLayoutRowConfig(count: 3, // 第二行显示的数量
seatSpacing: 10, // 第二行每个麦位的水平间距
seatSize: CGSize(width: 50, height: 50), // 第二行显示的每个麦位视图大小
alignment: .spaceAround) // 第二行麦位的对齐方式
let layoutConfig = SGSeatViewLayoutConfig(rowConfigs: [rowConfig1, rowConfig2],
rowSpacing: 10)

seatGridView.setLayoutMode(layoutMode: .free, layoutConfig: layoutConfig)
// 接口使用
import 'package:live_stream_core/live_stream_core.dart';

// 设置宫格布局
controller.setLayoutMode(LayoutMode.grid, null);

// 设置元素布局
controller.setLayoutMode(LayoutMode.focus, null);

// 设置垂直布局
controller.setLayoutMode(LayoutMode.vertical, null);

// 设置自定义布局
final rowConfig = SeatWidgetLayoutRowConfig(
count: 2,
seatSpacing: 20.0,
seatSize: const Size(80, 80),
alignment: SeatWidgetLayoutRowAlignment.spaceBetween);
final layoutConfig = SeatWidgetLayoutConfig(
rowConfigs: [rowConfig, rowConfig]);
controller.setLayoutMode(LayoutMode.free, layoutConfig);
自定义布局对齐方式示意图:


自定义麦位视图 UI

如果默认的麦位样式无法满足业务需求,您可以通过设置适配器( Adapter/Delegate )来完全托管麦位的渲染逻辑。

效果预览

默认麦位视图
自定义麦位视图示例








接口说明

Android
iOS
Flutter
Kotlin
interface SeatViewAdapter {
fun createSeatView(seatGridView: SeatGridView, seatInfo: TUIRoomDefine.SeatInfo): View
fun updateSeatView(seatGridView: SeatGridView, seatInfo: TUIRoomDefine.SeatInfo, seatView: View, )
fun updateUserVolume(seatGridView: SeatGridView, volume: Int, seatView: View)
}

fun setSeatViewAdapter(adapter: VoiceRoomDefine.SeatViewAdapter?)
参数
描述
seatGridView
当前语聊麦位组件。
seatInfo
当前麦位信息。
volume
当前麦上用户音量。
seatView
您自定义的麦位 view
adapter
自定义麦位适配器。
Swift
@objc public protocol SGSeatViewDelegate {
func seatGridView(_ view: SeatGridView, createSeatView seatInfo: TUISeatInfo) -> UIView?
func seatGridView(_ view: SeatGridView, updateSeatView seatInfo: TUISeatInfo, seatView: UIView)
func seatGridView(_ view: SeatGridView, updateUserVolume volume: Int, seatView: UIView)
}

public func setSeatViewDelegate(_ delegate: SGSeatViewDelegate)
参数
描述
view
当前语聊麦位组件。
seatInfo
当前麦位信息。
volume
当前麦上用户音量。
seatView
您自定义的麦位 view
delegate
自定义麦位 delegate
typedef SeatWidgetBuilder = Widget Function(
BuildContext context,
ValueNotifier<TUISeatInfo> seatInfoNotifier,
ValueNotifier<int> volumeNotifier);
参数
描述
context
上下文。
seatInfoNotifier
当前麦位信息。
volumeNotifier
当前麦上用户音量。

代码示例

Android
iOS
Flutter
如果默认的 UI 不满足需求,您可以自定义麦位 UI ,可参考如下方式快速设置麦位布局。
Kotlin
Java
val adapter = object : VoiceRoomDefine.SeatViewAdapter {
override fun createSeatView(seatGridView: SeatGridView, seatInfo: TUIRoomDefine.SeatInfo): View {
return TestSeatInfoView(context, seatGridView, seatInfo)
}

override fun updateSeatView(seatGridView: SeatGridView,seatInfo: TUIRoomDefine.SeatInfo, seatView: View) {
(seatView as TestSeatInfoView).updateSeatView(seatGridView, seatInfo)
}

override fun updateUserVolume(seatGridView: SeatGridView, volume: Int, customSeatView: View) {
(customSeatView as TestSeatInfoView).updateUserVolume(seatGridView, volume)
}
}

seatGridView.setSeatViewAdapter(adapter)

class TestSeatInfoView constructor(context: Context, seatGridView: SeatGridView, seatInfo: TUIRoomDefine.SeatInfo) : FrameLayout(context) {
init {
initView() //初始化view
}

fun updateSeatView(seatGridView: SeatGridView, seatInfo: TUIRoomDefine.SeatInfo) {
updateView(seatInfo) //更新自定义麦位视图UI
}

fun updateUserVolume(seatGridView: SeatGridView, volume: Int) {
updateUserVolume(volume) //更新音量变化UI
}
}
VoiceRoomDefine.SeatViewAdapter adapter = new VoiceRoomDefine.SeatViewAdapter() {
@Override
public View createSeatView(SeatGridView seatGridView, TUIRoomDefine.SeatInfo seatInfo) {
return new TestSeatInfoView(getApplicationContext(), seatGridView, seatInfo);
}

@Override
public void updateSeatView(SeatGridView seatGridView, TUIRoomDefine.SeatInfo seatInfo,
View customSeatView) {
((TestSeatInfoView) customSeatView).updateSeatView(seatGridView, seatInfo);
}

@Override
public void updateUserVolume(SeatGridView seatGridView, int volume, View customSeatView) {
((TestSeatInfoView) customSeatView).updateUserVolume(seatGridView, volume);
}
};
seatGridView.setSeatViewAdapter(adapter);

public class TestSeatInfoView extends FrameLayout {

public TestSeatInfoView(@NonNull Context context, SeatGridView seatGridView, TUIRoomDefine.SeatInfo seatInfo) {
super(context);
initView();
}

public void updateSeatView(SeatGridView seatGridView, TUIRoomDefine.SeatInfo seatInfo) {
updateView(seatInfo);
}

public void updateUserVolume(SeatGridView seatGridView, int volume) {
updateUserVolume(volume);
}
}
如果默认的 UI 不满足需求,您可以自定义麦位 UI ,可参考如下方式快速设置麦位布局。
Swift
import LiveStreamCore

class TestSeatViewDelegate: SGSeatViewDelegate {
func seatGridView(_ view: SeatGridView, createSeatView seatInfo: TUISeatInfo) -> UIView? {
return TestSeatInfoView(seatGridView: view, seatInfo: seatInfo)
}
func seatGridView(_ view: SeatGridView, updateSeatView seatInfo: TUISeatInfo, seatView: UIView) {
if let seatView = seatView as? TestSeatInfoView {
seatView.updateSeatView(seatGridView: view, seatInfo: seatInfo)
}
}
func seatGridView(_ view: SeatGridView, updateUserVolume volume: Int, seatView: UIView) {
if let seatView = seatView as? TestSeatInfoView {
seatView.updateUserVolume(seatGridView: view, volume: volume)
}
}
}

seatGridView.setSeatViewDelegate(TestSeatViewDelegate())

class TestSeatInfoView: UIView {
init(seatGridView: SeatGridView, seatInfo: TUISeatInfo) {
super.init(frame: .zero)
initView() // 初始化view
}

func updateSeatView(seatGridView: SeatGridView, seatInfo: TUISeatInfo) {
updateView(seatInfo) // 更新自定义麦位视图UI
}

func updateUserVolume(seatGridView: SeatGridView, volume: Int) {
updateUserVolume(volume) // 更新音量变化UI
}
}
如果默认的 UI 不满足需求,您可以自定义麦位 UI ,可通过 SeatGridWidget 的参数 seatWidgetBuilder 自定义指定麦位的 UI 样式。
// seatWidgetBuilder 定义
typedef SeatWidgetBuilder = Widget Function(
BuildContext context,
ValueNotifier<TUISeatInfo> seatInfoNotifier,
ValueNotifier<int> volumeNotifier);
// 使用示例
import 'package:live_stream_core/live_stream_core.dart';
import 'package:rtc_room_engine/rtc_room_engine.dart';

SeatGridWidget(
controller: controller,
onSeatWidgetTap: (TUISeatInfo seatInfo) {
// debugPrint('click seatWidget index:${seatInfo.index}');
},
seatWidgetBuilder: (
BuildContext context,
ValueNotifier<TUISeatInfo> seatInfoNotifier,
ValueNotifier<int> volumeNotifier) {
// 返回您的自定义麦位部件
return Container();
}
)

常见问题

自定义适配器后,如何获取麦位点击事件?

您需要在自定义 View 内部设置点击监听,在回调中处理业务逻辑。

切换布局后麦位数据会丢失吗?

不会。SeatGridView 内部维护了数据状态,setLayoutMode仅改变视觉排布,不会影响用户的上麦状态。

如何监听麦位列表的实时变化(如用户上麦/下麦)?

您无需在适配器中主动监听。SeatGridView 内部已实现了麦位注册监听,当任何麦位状态变化时,会自动回调 updateSeatView 方法。您只需在该方法中更新 UI 即可。