Browse Source
feat(live): 更新直播间UI并增强用户交互功能
feat(live): 更新直播间UI并增强用户交互功能
- 新增房间用户添加图标资源 - 优化主播展示区域,支持点击添加嘉宾功能 - 改进活跃说话人组件,使用网络图片并添加加载状态 - 实现用户上麦状态判断逻辑 - 添加嘉宾列表弹窗功能 - 优化视频占位图显示逻辑 - 调整UI布局和样式细节ios
4 changed files with 252 additions and 131 deletions
Split View
Diff Options
-
BINassets/images/room_user_add.png
-
1lib/generated/assets.dart
-
148lib/widget/live/live_room_active_speaker.dart
-
234lib/widget/live/live_room_anchor_showcase.dart
@ -1,54 +1,126 @@ |
|||
import 'package:cached_network_image/cached_network_image.dart'; |
|||
import 'package:dating_touchme_app/controller/discover/room_controller.dart'; |
|||
import 'package:dating_touchme_app/controller/global.dart'; |
|||
import 'package:dating_touchme_app/generated/assets.dart'; |
|||
import 'package:flutter/material.dart'; |
|||
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
|||
import 'package:get/get.dart'; |
|||
|
|||
class LiveRoomActiveSpeaker extends StatelessWidget { |
|||
const LiveRoomActiveSpeaker({super.key}); |
|||
|
|||
@override |
|||
Widget build(BuildContext context) { |
|||
return Row( |
|||
mainAxisAlignment: MainAxisAlignment.start, |
|||
children: [ |
|||
Stack( |
|||
clipBehavior: Clip.none, |
|||
children: [ |
|||
Container( |
|||
width: 34.w, |
|||
height: 34.w, |
|||
margin: EdgeInsets.only(left: 13.w), |
|||
child: ClipRRect( |
|||
borderRadius: BorderRadius.all(Radius.circular(34.w)), |
|||
child: Image.asset( |
|||
Assets.imagesUserAvatar, |
|||
width: 34.w, |
|||
height: 34.w, |
|||
// 获取 RoomController(在 Obx 外部获取,避免重复查找) |
|||
final roomController = Get.isRegistered<RoomController>() |
|||
? Get.find<RoomController>() |
|||
: null; |
|||
|
|||
if (roomController == null) { |
|||
return const SizedBox.shrink(); |
|||
} |
|||
|
|||
// 获取当前用户信息 |
|||
final currentUserId = GlobalData().userId ?? GlobalData().userData?.id; |
|||
final currentUserPhoto = GlobalData().userData?.profilePhoto ?? ''; |
|||
|
|||
return Obx(() { |
|||
// 访问响应式变量以触发更新 |
|||
final rtcChannelDetail = roomController.rtcChannelDetail.value; |
|||
final isLive = roomController.isLive.value; |
|||
|
|||
// 判断当前用户是否上麦 |
|||
bool isOnSeat = false; |
|||
if (currentUserId != null) { |
|||
// 方式1:检查当前用户是否在 maleInfo 或 femaleInfo 中(maleAudience/femaleAudience 角色) |
|||
if (rtcChannelDetail != null) { |
|||
final maleInfo = rtcChannelDetail.maleInfo; |
|||
final femaleInfo = rtcChannelDetail.femaleInfo; |
|||
|
|||
isOnSeat = |
|||
(maleInfo != null && |
|||
(maleInfo.userId == currentUserId || |
|||
maleInfo.miId == currentUserId)) || |
|||
(femaleInfo != null && |
|||
(femaleInfo.userId == currentUserId || |
|||
femaleInfo.miId == currentUserId)); |
|||
} |
|||
|
|||
// 方式2:如果 isLive 为 true,说明用户已连接(可能是 audience 角色) |
|||
// 如果已经在 maleInfo/femaleInfo 中,就不需要再检查 isLive |
|||
if (!isOnSeat && isLive) { |
|||
isOnSeat = true; |
|||
} |
|||
} |
|||
|
|||
// 确定显示的图标 |
|||
final micIcon = isOnSeat ? Assets.imagesMicOpen : Assets.imagesMicClose; |
|||
|
|||
return Row( |
|||
mainAxisAlignment: MainAxisAlignment.start, |
|||
children: [ |
|||
Stack( |
|||
clipBehavior: Clip.none, |
|||
children: [ |
|||
Container( |
|||
width: 34.w, |
|||
height: 34.w, |
|||
margin: EdgeInsets.only(left: 13.w), |
|||
child: ClipRRect( |
|||
borderRadius: BorderRadius.all(Radius.circular(34.w)), |
|||
child: currentUserPhoto.isNotEmpty |
|||
? CachedNetworkImage( |
|||
imageUrl: currentUserPhoto, |
|||
width: 34.w, |
|||
height: 34.w, |
|||
fit: BoxFit.cover, |
|||
placeholder: (context, url) => Container( |
|||
width: 34.w, |
|||
height: 34.w, |
|||
color: Colors.grey[300], |
|||
child: Center( |
|||
child: SizedBox( |
|||
width: 16.w, |
|||
height: 16.w, |
|||
child: CircularProgressIndicator( |
|||
strokeWidth: 2, |
|||
color: Colors.grey[600], |
|||
), |
|||
), |
|||
), |
|||
), |
|||
errorWidget: (context, url, error) => Image.asset( |
|||
Assets.imagesUserAvatar, |
|||
width: 34.w, |
|||
height: 34.w, |
|||
), |
|||
) |
|||
: Image.asset( |
|||
Assets.imagesUserAvatar, |
|||
width: 34.w, |
|||
height: 34.w, |
|||
), |
|||
), |
|||
), |
|||
), |
|||
Positioned( |
|||
bottom: -3.w, |
|||
left: 20.w, |
|||
child: Container( |
|||
width: 20.w, |
|||
height: 20.w, |
|||
decoration: BoxDecoration( |
|||
borderRadius: BorderRadius.all(Radius.circular(4.w)), |
|||
color: const Color.fromRGBO(0, 0, 0, .65), |
|||
), |
|||
child: Center( |
|||
child: Image.asset( |
|||
Assets.imagesMicClose, |
|||
width: 10.w, |
|||
height: 11.w, |
|||
Positioned( |
|||
bottom: -3.w, |
|||
left: 20.w, |
|||
child: Container( |
|||
width: 20.w, |
|||
height: 20.w, |
|||
decoration: BoxDecoration( |
|||
borderRadius: BorderRadius.all(Radius.circular(4.w)), |
|||
color: const Color.fromRGBO(0, 0, 0, .65), |
|||
), |
|||
child: Center( |
|||
child: Image.asset(micIcon, width: 10.w, height: 11.w), |
|||
), |
|||
), |
|||
), |
|||
), |
|||
], |
|||
), |
|||
], |
|||
); |
|||
], |
|||
), |
|||
], |
|||
); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
Write
Preview
Loading…
Cancel
Save