本文档将帮助您使用 AtomicXCore SDK 的 DeviceState、CallState 以及核心组件 CallCoreView,快速构建一个支持通话功能的 App。

准备工作
步骤1:开通服务
步骤2:在当前项目中导入 AtomicXCore
1. 安装组件:打开 AtomicXCore SDK,单击下载插件并导入 HBuilderX,选择需要集成的项目并单击确定。

2. 配置工程权限: 请在应用的 manifest.json 文件的 app-plus > distribute 节点下,确保添加了以下必要的权限:
Android 平台(
Android 节点):在 permissions 数组中,请确保包含以下权限:"<uses-permission android:name=\\"android.permission.RECORD_AUDIO\\" />","<uses-permission android:name=\\"android.permission.CAMERA\\"/>"
iOS 平台(
iOS 节点):在 privacyDescription 对象中,请确保包含以下描述:"NSCameraUsageDescription" : "应用需要访问您的相机以进行通话","NSMicrophoneUsageDescription" : "应用需要访问您的麦克风以进行通话"
在
UIBackgroundModes 数组中,添加 audio 以支持后台音频播放。"UIBackgroundModes" : [ "audio" ]
步骤3:实现登录逻辑
重要:
推荐在您 App 自身的用户账户登录成功后,再调用 LoginState 中的 login 方法,以确保登录业务逻辑的清晰和一致。
import { useLoginState } from "@/uni_modules/tuikit-atomic-x/state/LoginState";const { login } = useLoginState();const handleLogin = () => {login({sdkAppID: 1400000001, // 替换为您的 SDKAppIDuserID: "test_001", // 替换为您的 UserIDuserSig: "xxxxxxxxxx" // 替换为您的 UserSig})}
登录接口参数说明:
参数 | 类型 | 说明 |
sdkAppID | number | |
userID | string | 当前用户的唯一 ID,仅包含英文字母、数字、连字符和下划线。为避免多端登录冲突,请勿使用 1、123 等简单 ID。 |
userSig | string | 用于腾讯云鉴权的票据。请注意: 开发环境:您可以采用本地 GenerateTestUserSig.genTestSig 函数生成 userSig 或者通过 UserSig 辅助工具 生成临时的 UserSig。生产环境:为了防止密钥泄露,请务必采用服务端生成 UserSig 的方式。详细信息请参考 服务端生成 UserSig。 |
实现接听通话
步骤1:创建通话界面
您需要创建一个通话页面,当发起通话时唤起通话页面,实现方式如下:
1. 创建通话页面:您可以新建一个页面作为通话宿主页面,用于响应来电时的跳转逻辑。
2. 通话页面绑定 CallCoreView:通话视图核心组件,自动监听 CallState 数据并完成画面渲染,同时提供布局切换、头像与图标配置等 UI 定制化能力。
<call-core-view style="height: 50px; width: 50px;"></call-core-view>
说明:
CallCoreView 为原生组件,不需要在文件中单独进行 import。挂载在页面上即可使用。
CallCoreView 视图组件功能说明:
功能 | 说明 | 参考文档 |
设置布局模式 | 支持自由切换布局模式。若未设置,将根据通话人数自动适配布局。 | |
设置头像 | 支持通过传入头像资源路径,为特定用户自定义头像。 | |
设置音量提示图标 | 支持根据不同音量等级,配置个性化的音量指示图标。 | |
设置网络提示图标 | 支持根据实时网络质量,配置对应的网络状态提示图标。 | |
设置等待接听用户的动画 | 在多人通话场景下,支持传入 GIF 图像路径,为待接听状态的用户展示动画。 |
步骤2:添加通话控制按钮
您可以参考 DeviceState 、CallState 提供的 API ,自定义添加您的按钮。
DeviceState 功能说明:麦克风(开关 / 音量)、摄像头(开关 / 切换 / 画质)、屏幕共享,设备状态实时监听。建议将对应方法绑定至按钮点击事件,并通过监听设备状态变更来实时刷新按钮的 UI 状态。
CallState 功能说明:接听、挂断、拒接等核心通话控制能力。建议将对应方法绑定至按钮点击事件,并监听通话状态的变化,以确保按钮显示与当前通话阶段保持同步。
图标资源下载:按钮图标可以直接从 GitHub 下载。这些图标由我们的设计师专为 TUICallKit 打造,无版权风险,可放心使用。
以下是添加"接听"和"拒接"按钮的实现方式:
1. 添加接听按钮:添加"接听"按钮,将其点击事件绑定至 accept 方法。
<template><view class="btn" @tap="handleAccept"><image class="btn-img" :src="ACCEPT_SRC"></image><text class="btn-text">接听</text></view></template><script setup lang="ts">import ACCEPT_SRC from "../../../static/icon/accept.png"; // 替换为您项目的真实图标路径import { useCallState } from '@/uni_modules/tuikit-atomic-x/state/CallState';const { accept } = useCallState();const handleAccept = () => {accept();};</script><style scoped>.btn {width: 60px;margin: 10px 20px;}.btn-img {width: 60px;height: 60px;border-radius: 140px;}.btn-text {font-size: 12px;color: #d5e0f2;font-weight: 400;text-align: center;margin-top: 10px;}</style>
2. 添加拒接按钮:添加"拒接"按钮,将其点击事件分别绑定至 reject 方法。
<template><view class="btn" @tap="handleReject"><image class="btn-img" :src="REJECT_SRC"></image><text class="btn-text">拒绝</text></view></template><script setup lang="ts">import REJECT_SRC from "../../../static/icon/hangup.png"; // 替换为您项目的真实图标路径import { useCallState } from '@/uni_modules/tuikit-atomic-x/state/CallState';const { reject } = useCallState();const handleReject = () => {reject();};</script><style scoped>.btn {margin: 10px 20px;}.btn-img {width: 60px;height: 60px;border-radius: 140px;}.btn-text {font-size: 12px;color: #d5e0f2;font-weight: 400;text-align: center;margin-top: 10px;}</style>
3. 拨打方取消通话或您拒接时销毁界面:无论拨打方取消呼叫,还是接收方拒接,均会触发
onCallEnded(通话结束)事件。建议监听此事件,以便在通话终止时及时关闭(销毁)通话界面。import { useCallState } from '@/uni_modules/tuikit-atomic-x/state/CallState';import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';const { addCallListener } = useCallState();const { closeLocalCamera, closeLocalMicrophone } = useDeviceState();/*** 初始化通话服务(最小示例:仅处理通话结束事件并回退页面)建议在应用初始化时执行该函数*/export function initCallService() {addCallListener('onCallEnded', (event: string) => {let res: any;try {res = JSON.parse(event);} catch (error) {console.error('[CallService] onCallEnded parse error:', error);return;}console.log('[CallService] onCallEnded, reason:', res.reason);// 关闭本地设备closeLocalCamera();closeLocalMicrophone();// 页面回退const pages = getCurrentPages();if (pages.length > 1) {uni.navigateBack({ delta: 1 });} else {uni.redirectTo({ url: '/pages/index/index' }); // 示例路径:请结合您的项目真实路径进行修改}});}
步骤3:来电唤起通话界面
在您的项目中监听来电事件(
onCallReceived),当收到来电时唤起通话页面。实现方式如下:1. 监听来电事件:订阅
onCallReceived 事件。2. 唤起通话界面:收到来电唤起通话页面。
import { useCallState } from '@/uni_modules/tuikit-atomic-x/state/CallState';const { addCallListener } = useCallState();// 通话页面路由const CALL_PAGE = '/uni_modules/tuikit-atomic-x/pages/call'; // 替换为您在步骤1 中创建的真实路径// 建议在应用初始化的时候执行该方法export function initCallService() {addCallListener('onCallReceived', (event: string) => {uni.navigateTo({url: CALL_PAGE});});}
步骤4:来电播放提示
在您的项目中监听来电事件(
onCallReceived),当收到来电时播放铃声。实现方式如下:1. 监听来电事件:订阅
onCallReceived 事件。2. 唤起通话界面:收到来电播放铃声。
import { watch } from 'vue';import { useCallState } from '@/uni_modules/tuikit-atomic-x/state/CallState';const { addCallListener, selfInfo } = useCallState();/*** 创建或获取音频播放实例(单例复用)*/function ensureAudioContext() {if (!uni.$innerAudioContext) {const ctx = uni.createInnerAudioContext();ctx.onError((err: any) => {console.error('[CallService] innerAudioContext onError:', err?.errCode, err?.errMsg || err);});uni.$innerAudioContext = ctx;}return uni.$innerAudioContext;}/*** 播放铃声* @param src - 铃声文件路径*/function playRingtone(src: string) {const ctx = ensureAudioContext();try {ctx.stop();} catch (_e) {}ctx.src = src;ctx.loop = true;ctx.autoplay = true;setTimeout(() => {try {ctx.play();} catch (e) {console.warn('[CallService] playRingtone play() error:', e);}}, 50);}/*** 停止铃声*/function stopRingtone() {if (uni.$innerAudioContext) {try {uni.$innerAudioContext.loop = false;uni.$innerAudioContext.stop();} catch (e) {console.warn('[CallService] stopRingtone error:', e);}}}export { playRingtone, stopRingtone };// 在应用启动的时候执行该方法export function initCallService() {ensureAudioContext();// 监听通话状态变化:接通(status=2)或结束(status=0)时停止铃声watch(() => selfInfo.value, (newVal) => {if (newVal?.status === 2 || newVal?.status === 0) {stopRingtone();}}, { immediate: true, deep: true });// 收到来电时播放铃声addCallListener('onCallReceived', () => {playRingtone('/static/audio/ring.mp3');});// 通话结束时停止铃声addCallListener('onCallEnded', () => {stopRingtone();});}
步骤5:来电打开媒体设备
收到来电时,您可以通过
onCallReceived 事件获取本次通话的媒体类型。为了提供更佳的用户体验,建议在唤起通话界面时,根据通话类型预先开启对应的媒体设备。实现步骤如下:1. 监听来电事件:订阅
onCallReceived 事件。2. 根据来电媒体类型打开设备:若为语音通话仅开启麦克风,若为视频通话开启麦克风和摄像头。
import { useCallState } from '@/uni_modules/tuikit-atomic-x/state/CallState';import { useDeviceState } from '@/uni_modules/tuikit-atomic-x/state/DeviceState';const { addCallListener } = useCallState();const { openLocalCamera, openLocalMicrophone } = useDeviceState();// 通话页面路由const CALL_PAGE = '/uni_modules/tuikit-atomic-x/pages/call'; // 替换为您在步骤1 中创建的真实路径// 在应用启动的时候执行该方法export function initCallService() {addCallListener('onCallReceived', (event: string) => {let res: any;try {res = JSON.parse(event);} catch (error) {console.error('[CallService] onCallReceived parse error:', error);return;}// 视频通话时打开摄像头if (res.mediaType === 1) {openLocalCamera({ isFront: true });}// 打开麦克风openLocalMicrophone();// 跳转到通话页面uni.navigateTo({url: CALL_PAGE});});}
运行效果
当您完成以上 6 步后,"接听一通电话"运行效果如下:

定制页面
CallCoreView 提供了完善的 UI 定制能力,支持头像及音量提示等图标的自由替换。为助力快速集成,您可以直接从 GitHub 下载。这些图标由我们的设计师专为 TUICallKit 打造,无版权风险,可放心使用。
自定义音量提示的图标
您可以通过设置 CallCoreView 组件的
volumeLevelIcons 属性来设置音量大小等级不同的提示图标。
volumeLevelIcons 属性设置示例代码:<template><view class="call-view-container"><view :style="{ height: systemInfo?.windowHeight + 'px', width: systemInfo?.safeArea?.width + 'px' }"><call-core-view:style="{ height: systemInfo?.windowHeight + 'px', width: systemInfo?.safeArea?.width + 'px' }":volumeLevelIcons="volumeLevelIcons"></call-core-view></view></view></template><script setup>import { ref, onMounted } from 'vue';const systemInfo = ref({});/*** 将 /static/ 相对路径转为原生层可用的本地绝对路径*/function toAbsolutePath(relativePath) {if (plus && plus.io && plus.io.convertLocalFileSystemURL) {return plus.io.convertLocalFileSystemURL(relativePath);}return relativePath;}/*** 批量转换对象中所有 value 的路径为绝对路径*/function convertIconPaths(iconMap) {const result = {};Object.keys(iconMap).forEach(key => {result[key] = toAbsolutePath(iconMap[key]);});return result;}// 音量等级图标:key 为等级名称,value 为图标本地绝对路径const volumeLevelIcons = ref(convertIconPaths({"Mute": "/static/images/callview-self-mute.png", // 可以替换您项目中的实际图标路径"Low": "/static/images/callview-network.png" // 可以替换您项目中的实际图标路径}));onMounted(() => {uni.getSystemInfo({success: (res) => {systemInfo.value = res;}});});</script><style>.call-view-container {background: rgba(15, 16, 20, 0.5);overflow: hidden;}</style>
说明:
uni-app 传递给原生层的参数只支持本地路径,因此需要将相对路径转化为本地路径
属性参数详细说明:
参数 | 类型 | 是否必填 | 说明 |
icons | [String: String] | 是 | 音量等级与图标资源的映射表。结构说明如下: key ( VolumeLevel ) 表示音量等级: Mute:表示麦克风关闭,静音状态。Low:表示音量范围 (0-25]。Medium:表示音量范围 (25-50]。High:表示音量范围 (50-75]。Peak:表示音量范围 (75-100]。Value ( String ) 表示对应音量等级的图标资源路径。 |
音量提示图标:
自定义网络提示的图标
您可以设置 CallCoreView 组件的
networkQualityIcons 属性设置不同网络状态的提示图标。
networkQualityIcons 属性设置示例代码:<template><view class="call-view-container"><view :style="{ height: systemInfo?.windowHeight + 'px', width: systemInfo?.safeArea?.width + 'px' }"><call-core-view:style="{ height: systemInfo?.windowHeight + 'px', width: systemInfo?.safeArea?.width + 'px' }":networkQualityIcons="networkQualityIcons"></call-core-view></view></view></template><script setup>import { ref, onMounted } from 'vue';const systemInfo = ref({});/*** 将 /static/ 相对路径转为原生层可用的本地绝对路径*/function toAbsolutePath(relativePath) {if (plus && plus.io && plus.io.convertLocalFileSystemURL) {return plus.io.convertLocalFileSystemURL(relativePath);}return relativePath;}/*** 批量转换对象中所有 value 的路径为绝对路径*/function convertIconPaths(iconMap) {const result = {};Object.keys(iconMap).forEach(key => {result[key] = toAbsolutePath(iconMap[key]);});return result;}const networkQualityIcons = ref(convertIconPaths({"BAD": "/static/images/callview-network-bad.png", // 可以替换您项目中的实际图标路径"VERY_BAD": "/static/images/callview-network-bad.png" // 可以替换您项目中的实际图标路径}));onMounted(() => {uni.getSystemInfo({success: (res) => {systemInfo.value = res;}});});</script><style>.call-view-container {background: rgba(15, 16, 20, 0.5);overflow: hidden;}</style>
networkQualityIcons 接口参数详细说明:参数 | 类型 | 是否必填 | 说明 |
icons | [String: String] | 是 | 网络质量与图标资源的映射表。结构说明如下: Key ( String):表示网络质量等级: UNKNOWN:未知网络状态。EXCELLENT:网络状态极佳。GOOD:网络状态较好。POOR:网络状态较差。BAD:网络状态差。VERY_BAD:网络状态极差。DOWN:网络断开。Value ( String ):对应网络状态的图标资源路径。 |
网络较差的提示图标:
图标 | 说明 | 下载地址 |
![]() | 【图标含义】网络较差的提示图标。 【推荐用法】您可以将该图标等级设置为 BAD、VERY_BAD 或 DOWN ,当网络较差时显示该图标。 |
自定义默认头像
您可以设置 CallCoreView 的
participantAvatars 属性设置用户头像。建议您监听响应式数据 allParticipants(所有参与通话的成员):当获取到用户头像时设置并展示;若用户未设置头像或加载失败,则显示默认头像(占位图)。participantAvatars 属性设置示例代码:<template><view class="call-view-container"><view :style="{ height: systemInfo?.windowHeight + 'px', width: systemInfo?.safeArea?.width + 'px' }"><call-core-view:style="{ height: systemInfo?.windowHeight + 'px', width: systemInfo?.safeArea?.width + 'px' }":participantAvatars="participantAvatars"></call-core-view></view></view></template><script setup>import { ref, watch, onMounted } from 'vue';import { useCallState } from '@/uni_modules/tuikit-atomic-x/state/CallState';const { allParticipants } = useCallState();const systemInfo = ref({});const participantAvatars = ref({});const avatarCache = {};const DEFAULT_AVATAR_URL = "https://liteav.sdk.qcloud.com/app/res/picture/voiceroom/avatar/user_avatar1.png";let defaultAvatarLocalPath = "";let defaultAvatarReady = false;/*** 将相对路径转为原生层可用的本地绝对路径*/function toAbsolutePath(relativePath) {if (plus && plus.io && plus.io.convertLocalFileSystemURL) {return plus.io.convertLocalFileSystemURL(relativePath);}return relativePath;}/*** 下载头像并缓存,返回本地绝对路径*/function downloadAvatar(url) {if (avatarCache[url]) {return Promise.resolve(avatarCache[url]);}return new Promise((resolve) => {uni.downloadFile({url,success: (res) => {if (res.statusCode === 200) {const absolutePath = toAbsolutePath(res.tempFilePath);avatarCache[url] = absolutePath;resolve(absolutePath);} else {resolve(defaultAvatarLocalPath || "");}},fail: () => {resolve(defaultAvatarLocalPath || "");}});});}// 预下载默认头像const defaultAvatarPromise = downloadAvatar(DEFAULT_AVATAR_URL).then(localPath => {defaultAvatarLocalPath = localPath;defaultAvatarReady = true;// 默认头像就绪后,补刷一次参与者头像if (allParticipants.value && allParticipants.value.length > 0) {updateParticipantAvatars(allParticipants.value);}});/*** 根据参与者列表,下载头像并构建 { userId: localPath } 映射*/async function updateParticipantAvatars(participants) {if (!participants || participants.length === 0) {participantAvatars.value = {};return;}if (!defaultAvatarReady && defaultAvatarPromise) {await defaultAvatarPromise;}const avatarMap = {};const tasks = [];participants.forEach(participant => {if (participant.id && participant.avatarURL) {tasks.push(downloadAvatar(participant.avatarURL).then(localPath => {avatarMap[participant.id] = localPath;}));} else if (participant.id) {avatarMap[participant.id] = defaultAvatarLocalPath || "";}});await Promise.all(tasks);participantAvatars.value = avatarMap;}// 监听参与者变化,更新头像映射watch(() => allParticipants.value, async (newVal) => {if (!newVal) return;await updateParticipantAvatars(newVal);}, { immediate: true, deep: true });onMounted(() => {uni.getSystemInfo({success: (res) => {systemInfo.value = res;}});});</script><style>.call-view-container {background: rgba(15, 16, 20, 0.5);overflow: hidden;}</style>
participantAvatars 属性参数详细说明:参数 | 类型 | 是否必填 | 说明 |
avatars | [String: String] | 是 | 用户头像映射表。字典结构说明如下: Key:用户的 userID。 Value:该用户的头像资源绝对路径。 |
默认头像资源:
图标 | 说明 | 下载地址 |
![]() | 【图标含义】默认头像。 【推荐用法】当用户头像加载失败或无头像时,您可以给该用户设置此默认头像。 |
自定义 loading 动画
您可以设置 CallCoreView 的
waitingAnimation 属性,为等待中用户设置等待动画获得更好的体验。
waitingAnimation 属性设置示例代码:<template><view class="call-view-container"><view :style="{ height: systemInfo?.windowHeight + 'px', width: systemInfo?.safeArea?.width + 'px' }"><call-core-view:style="{ height: systemInfo?.windowHeight + 'px', width: systemInfo?.safeArea?.width + 'px' }":waitingAnimation="waitingAnimation"></call-core-view></view></view></template><script setup>import { ref, onMounted } from 'vue';const systemInfo = ref({});/*** 将 /static/ 相对路径转为原生层可用的本地绝对路径*/function toAbsolutePath(relativePath) {if (plus && plus.io && plus.io.convertLocalFileSystemURL) {return plus.io.convertLocalFileSystemURL(relativePath);}return relativePath;}// 等待动画 GIF:传入本地绝对路径供原生组件渲染const waitingAnimation = ref(toAbsolutePath("/static/images/callview-loading.gif")); // 可以替换您项目中的实际图标路径onMounted(() => {uni.getSystemInfo({success: (res) => {systemInfo.value = res;}});});</script><style>.call-view-container {background: rgba(15, 16, 20, 0.5);overflow: hidden;}</style>
waitingAnimation 接口参数详细说明:参数 | 类型 | 是否必填 | 说明 |
path | String | 是 | GIF 格式图像资源的绝对路径。 |
等待接听的动画:
图标 | 说明 | 下载地址 |
![]() | 【图标含义】用户等待接听动画。 【推荐用法】群组通话时设置的动画。设置后,当用户的状态为等待接听时,显示该动画。 |
添加通话计时提示
通话计时可通过响应式数据 activeCall 的
duration 字段实时获得,实时显示通话计时的实现方式如下:1. 绑定通话计时数据:将
activeCall.duration 字段绑定至 UI 。该字段为响应式数据,会自动驱动 UI 实时刷新,无需手动维护定时器。<template><view v-if="isConnected" class="call-timer"><text class="timer-text">{{ formattedTime }}</text></view></template><script setup lang="ts">import { computed } from 'vue';import { useCallState } from '@/uni_modules/tuikit-atomic-x/state/CallState';const { selfInfo, activeCall } = useCallState();const isConnected = computed(() => {return selfInfo.value?.status === 2;});const formattedTime = computed(() => {const duration = activeCall.value?.duration ?? 0;const hours = Math.floor(duration / 3600);const minutes = Math.floor((duration % 3600) / 60);const seconds = duration % 60;const pad = (n: number) => n.toString().padStart(2, '0');if (hours > 0) {return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;}return `${pad(minutes)}:${pad(seconds)}`;});</script><style scoped>.call-timer {display: flex;align-items: center;justify-content: center;}.timer-text {font-size: 28rpx;color: #FFFFFF;font-weight: 400;}</style>
更多功能
自定义用户头像/昵称
setSelfInfo 示例代码:
import { useLoginState } from "@/uni_modules/tuikit-atomic-x/state/LoginState";const { setSelfInfo } = useLoginState();/*** 设置当前登录用户的个人信息(昵称、头像等)*/export const setSelfUserInfo = (userID: string, nickname: string, avatarURL: string): void => {setSelfInfo({userProfile: {userID,nickname,avatarURL,},success: () => {console.log('用户信息设置成功');},fail: (errCode: number, errMsg: string) => {console.error('用户信息设置失败:', errCode, errMsg);},});};
setSelfInfo 接口参数详细说明:
参数 | 类型 | 是否必填 | 说明 |
userProfile | UserProfile | 是 | 用户信息结构体: userID:用户的 IDavatarURL:用户头像的 URLnickname:用户的昵称更多字段详情可参考 UserProfile。 |
切换布局模式
CallCoreView 内置三种布局模式,您可以设置
layoutTemplate 属性来设置布局模式。若未主动配置,CallCoreView 将根据通话人数自动适配:1 V 1 场景下默认采用 Float 模式,多人通话场景下则自动切换为 Grid 模式。不同布局模式的说明如下:Float 模式 | Grid 模式 | PIP 模式 |
![]() | ![]() | ![]() |
布局逻辑:呼叫等待时全屏显示己方画面;接通后全屏显示对方画面,己方画面以悬浮小窗展示。 交互特性:支持小窗拖拽移动,点击小窗可实现大小画面互换。 | 布局逻辑:所有成员画面呈网格状平铺排列成宫格模式布局,适用 2 人以上通话,支持点击放大画面功能。 交互特性:支持点击特定成员画面放大查看。 | 布局逻辑:1 v 1 场景固定显示对方画面,多人场景:采用当前发言者(Active Speaker) 策略,自动识别并全屏展示正在说话的用户。 交互特性:等待时显示自己的画面,接通后还会显示通话计时。 |
layoutTemplate 属性设置示例代码:<template><view class="call-view-container"><view :style="{ height: systemInfo?.windowHeight + 'px', width: systemInfo?.safeArea?.width + 'px' }"><call-core-view:style="{ height: systemInfo?.windowHeight + 'px', width: systemInfo?.safeArea?.width + 'px' }":layoutTemplate="layoutTemplate"></call-core-view></view></view></template><script setup>import { ref, watch, onMounted } from 'vue';import { useCallState } from '@/uni_modules/tuikit-atomic-x/state/CallState';const { activeCall } = useCallState();const systemInfo = ref({});// 布局模板:'Float' 单人浮窗布局,'Grid' 多人宫格布局const layoutTemplate = ref("Grid");// 根据通话信息自动切换布局:多人或群聊用 Grid,单人用 Floatwatch(() => activeCall.value, (newValue) => {if (!newValue || !newValue.inviteeIds) {return;}const newTemplate = (newValue.inviteeIds.length > 1 || newValue.chatGroupId !== '') ? 'Grid' : 'Float';if (layoutTemplate.value !== newTemplate) {layoutTemplate.value = newTemplate;}}, { immediate: true, deep: true });onMounted(() => {uni.getSystemInfo({success: (res) => {systemInfo.value = res;}});});</script><style>.call-view-container {background: rgba(15, 16, 20, 0.5);overflow: hidden;}</style>
layoutTemplate 属性参数详细说明:参数 | 类型 | 说明 |
layoutTemplate | String | CallCoreView 的布局模式 Float: 布局逻辑:呼叫等待时全屏显示己方画面;接通后全屏显示对方画面,己方画面以悬浮小窗展示。 交互特性:支持小窗拖拽移动,点击小窗可实现大小画面互换。 Grid: 布局逻辑:所有成员画面呈网格状平铺排列成宫格模式布局,适用 2 人以上通话,支持点击放大画面功能。 交互特性:支持点击特定成员画面放大查看。 PIP: 布局逻辑:1v1 场景固定显示对方画面,多人场景:采用当前发言者(Active Speaker) 策略,自动识别并全屏展示正在说话的用户。 交互特性:等待时显示自己的画面,接通后还会显示通话计时。 |
下一步
常见问题
如何保证通话过程中屏幕常亮?
如何禁止系统侧滑返回上一个页面的行为?
Android 端可以通过 onBackPress 拦截系统侧滑和物理返回,示例代码如下:
注意:
<script setup>import { onBackPress } from '@dcloudio/uni-app'// 拦截系统侧滑和物理返回键,防止通话中误退出onBackPress((option) => {if (option.from === 'backbutton') {return true; // 返回 true 阻止默认回退行为}});</script>
联系我们















