Files
xueguang_flutter_app/lib/pages/teacher/room/widgets/content_view.dart
2025-11-28 13:31:23 +08:00

155 lines
4.5 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:app/config/config.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
import '../viewmodel/tch_room_vm.dart';
import 'student_item.dart';
class ContentView extends StatefulWidget {
const ContentView({super.key});
@override
State<ContentView> createState() => _ContentViewState();
}
class _ContentViewState extends State<ContentView> {
//声网数据
RtcEngine? _engine;
@override
void initState() {
super.initState();
_initRtc();
}
@override
void dispose() {
super.dispose();
WakelockPlus.disable();
_dispose();
}
void _initRtc() async {
final vm = context.read<TchRoomVM>();
_engine = createAgoraRtcEngine();
//初始化 RtcEngine设置频道场景为 channelProfileLiveBroadcasting直播场景
await _engine!.initialize(
RtcEngineContext(
appId: Config.swAppId,
channelProfile: ChannelProfileType.channelProfileCommunication,
),
);
// 启用视频模块
await _engine!.enableVideo();
// 开启本地预览
await _engine!.startPreview();
final status = await _engine!.getConnectionState();
WakelockPlus.enable();
if (status == ConnectionStateType.connectionStateDisconnected) {
//加入频道
await _engine!.joinChannel(
token: vm.rtcToken!.token,
channelId: vm.rtcToken!.channel,
uid: vm.rtcToken!.uid,
options: ChannelMediaOptions(
// 自动订阅所有视频流
autoSubscribeVideo: true,
// 自动订阅所有音频流
autoSubscribeAudio: true,
// 发布摄像头采集的视频
publishCameraTrack: true,
// 发布麦克风采集的音频
publishMicrophoneTrack: true,
// 设置用户角色为 clientRoleBroadcaster主播或 clientRoleAudience观众
clientRoleType: ClientRoleType.clientRoleBroadcaster,
),
);
}
}
//销毁
Future<void> _dispose() async {
if (_engine != null) {
await _engine!.leaveChannel();
await _engine!.release();
}
}
@override
Widget build(BuildContext context) {
return Consumer<TchRoomVM>(
builder: (context, vm, _) {
if (vm.students.isEmpty) {
return Align(
child: Text(
'学生还没入场',
style: TextStyle(color: Colors.white),
),
);
}
//选中的学生
final activeStudent = vm.students.firstWhere((t) => t.userId == vm.activeSId);
//其他学生
final otherStudents = vm.students.where((t) => t.userId != vm.activeSId).toList()
..sort((a, b) => b.handup.compareTo(a.handup));
return Padding(
padding: const EdgeInsets.all(10),
child: Row(
spacing: 15,
children: [
Expanded(
child: Stack(
children: [
StudentItem(
user: activeStudent,
engine: _engine,
),
Positioned(
top: 0,
left: 0,
child: Container(
width: 150,
color: Colors.black,
child: AspectRatio(
aspectRatio: 1 / 1.2,
child: AgoraVideoView(
controller: VideoViewController(
rtcEngine: _engine!,
canvas: const VideoCanvas(uid: 0),
),
),
),
),
),
],
),
),
SizedBox(
width: 300,
child: ListView.separated(
itemBuilder: (_, index) {
var item = otherStudents.elementAt(index);
return SizedBox(
height: 250,
child: StudentItem(
user: item,
engine: _engine,
),
);
},
separatorBuilder: (_, __) => SizedBox(height: 15),
itemCount: otherStudents.length,
),
),
],
),
);
},
);
}
}