Merge branch 'feature-liveRoomRender'

This commit is contained in:
guozhigq
2024-09-22 23:16:42 +08:00
4 changed files with 150 additions and 136 deletions

View File

@ -1,11 +1,13 @@
class RoomInfoModel {
RoomInfoModel({
this.roomId,
this.isPortrait,
this.liveStatus,
this.liveTime,
this.playurlInfo,
});
int? roomId;
bool? isPortrait;
int? liveStatus;
int? liveTime;
PlayurlInfo? playurlInfo;
@ -13,6 +15,7 @@ class RoomInfoModel {
RoomInfoModel.fromJson(Map<String, dynamic> json) {
roomId = json['room_id'];
liveStatus = json['live_status'];
isPortrait = json['is_portrait'];
liveTime = json['live_time'];
playurlInfo = PlayurlInfo.fromJson(json['playurl_info']);
}

View File

@ -48,6 +48,7 @@ class LiveRoomController extends GetxController {
// 直播间弹幕开关 默认打开
RxBool danmakuSwitch = true.obs;
late String buvid;
RxBool isPortrait = false.obs;
@override
void onInit() {
@ -101,6 +102,7 @@ class LiveRoomController extends GetxController {
Future queryLiveInfo() async {
var res = await LiveHttp.liveRoomInfo(roomId: roomId, qn: currentQn);
if (res['status']) {
isPortrait.value = res['data'].isPortrait;
List<CodecItem> codec =
res['data'].playurlInfo.playurl.stream.first.format.first.codec;
CodecItem item = codec.first;

View File

@ -115,6 +115,9 @@ class _LiveRoomPageState extends State<LiveRoomPage>
plPlayerController = _liveRoomController.plPlayerController;
return PLVideoPlayer(
controller: plPlayerController,
alignment: _liveRoomController.isPortrait.value
? Alignment.topCenter
: Alignment.center,
bottomControl: BottomControl(
controller: plPlayerController,
liveRoomCtr: _liveRoomController,
@ -178,10 +181,83 @@ class _LiveRoomPageState extends State<LiveRoomPage>
),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AppBar(
Obx(
() => SizedBox(
height: MediaQuery.of(context).padding.top +
(_liveRoomController.isPortrait.value ||
MediaQuery.of(context).orientation ==
Orientation.landscape
? 0
: kToolbarHeight),
),
),
PopScope(
canPop: plPlayerController.isFullScreen.value != true,
onPopInvoked: (bool didPop) {
if (plPlayerController.isFullScreen.value == true) {
plPlayerController.triggerFullScreen(status: false);
}
if (MediaQuery.of(context).orientation ==
Orientation.landscape) {
verticalScreen();
}
},
child: Obx(
() => Container(
width: Get.size.width,
height: MediaQuery.of(context).orientation ==
Orientation.landscape
? Get.size.height
: !_liveRoomController.isPortrait.value
? Get.size.width * 9 / 16
: Get.size.height -
MediaQuery.of(context).padding.top,
clipBehavior: Clip.hardEdge,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(6)),
),
child: videoPlayerPanel,
),
),
),
],
),
// 定位 快速滑动到底部
Positioned(
right: 20,
bottom: MediaQuery.of(context).padding.bottom + 80,
child: SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 4),
end: const Offset(0, 0),
).animate(CurvedAnimation(
parent: fabAnimationCtr,
curve: Curves.easeInOut,
)),
child: ElevatedButton.icon(
onPressed: () {
_scrollToBottom();
},
icon: const Icon(Icons.keyboard_arrow_down), // 图标
label: const Text('新消息'), // 文字
style: ElevatedButton.styleFrom(
// primary: Colors.blue, // 按钮背景颜色
// onPrimary: Colors.white, // 按钮文字颜色
padding: const EdgeInsets.fromLTRB(14, 12, 20, 12), // 按钮内边距
),
),
),
),
// 顶栏
Positioned(
top: 0,
left: 0,
right: 0,
child: AppBar(
centerTitle: false,
titleSpacing: 0,
backgroundColor: Colors.transparent,
@ -213,8 +289,8 @@ class _LiveRoomPageState extends State<LiveRoomPage>
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_liveRoomController.roomInfoH5.value
.anchorInfo!.baseInfo!.uname!,
_liveRoomController.roomInfoH5.value.anchorInfo!
.baseInfo!.uname!,
style: const TextStyle(fontSize: 14),
),
const SizedBox(height: 1),
@ -238,77 +314,33 @@ class _LiveRoomPageState extends State<LiveRoomPage>
},
),
),
PopScope(
canPop: plPlayerController.isFullScreen.value != true,
onPopInvoked: (bool didPop) {
if (plPlayerController.isFullScreen.value == true) {
plPlayerController.triggerFullScreen(status: false);
}
if (MediaQuery.of(context).orientation ==
Orientation.landscape) {
verticalScreen();
}
},
child: SizedBox(
width: Get.size.width,
height: MediaQuery.of(context).orientation ==
Orientation.landscape
? Get.size.height
: Get.size.width * 9 / 16,
child: videoPlayerPanel,
),
),
// 显示消息的列表
buildMessageListUI(
// 消息列表
Obx(
() => Positioned(
top: MediaQuery.of(context).padding.top +
kToolbarHeight +
(_liveRoomController.isPortrait.value
? Get.size.width
: Get.size.width * 9 / 16),
bottom: 110,
left: 0,
right: 0,
child: buildMessageListUI(
context,
_liveRoomController,
_scrollController,
),
// Container(
// padding: const EdgeInsets.only(
// left: 14, right: 14, top: 4, bottom: 4),
// margin: const EdgeInsets.only(
// bottom: 6,
// left: 14,
// ),
// decoration: BoxDecoration(
// color: Colors.grey.withOpacity(0.1),
// borderRadius: const BorderRadius.all(Radius.circular(20)),
// ),
// child: Obx(
// () => AnimatedSwitcher(
// duration: const Duration(milliseconds: 300),
// transitionBuilder:
// (Widget child, Animation<double> animation) {
// return FadeTransition(opacity: animation, child: child);
// },
// child: Text.rich(
// key:
// ValueKey(_liveRoomController.joinRoomTip['userName']),
// TextSpan(
// style: const TextStyle(color: Colors.white),
// children: [
// TextSpan(
// text:
// '${_liveRoomController.joinRoomTip['userName']} ',
// style: TextStyle(
// color: Colors.white.withOpacity(0.6),
// ),
// ),
// TextSpan(
// text:
// '${_liveRoomController.joinRoomTip['message']}',
// style: const TextStyle(color: Colors.white),
// ),
// ],
// ),
// ),
// ),
// ),
// ),
const SizedBox(height: 10),
// 弹幕输入框
Container(
),
),
// 消息输入框
Visibility(
visible: MediaQuery.of(context).orientation == Orientation.portrait,
child: Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
padding: EdgeInsets.only(
left: 14,
right: 14,
@ -384,32 +416,6 @@ class _LiveRoomPageState extends State<LiveRoomPage>
],
),
),
],
),
// 定位 快速滑动到底部
Positioned(
right: 20,
bottom: MediaQuery.of(context).padding.bottom + 80,
child: SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 4),
end: const Offset(0, 0),
).animate(CurvedAnimation(
parent: fabAnimationCtr,
curve: Curves.easeInOut,
)),
child: ElevatedButton.icon(
onPressed: () {
_scrollToBottom();
},
icon: const Icon(Icons.keyboard_arrow_down), // 图标
label: const Text('新消息'), // 文字
style: ElevatedButton.styleFrom(
// primary: Colors.blue, // 按钮背景颜色
// onPrimary: Colors.white, // 按钮文字颜色
padding: const EdgeInsets.fromLTRB(14, 12, 20, 12), // 按钮内边距
),
),
),
),
],
@ -467,7 +473,7 @@ Widget buildMessageListUI(
alignment: Alignment.centerLeft,
child: Container(
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1),
color: Colors.black.withOpacity(0.3),
borderRadius: const BorderRadius.all(Radius.circular(20)),
),
margin: EdgeInsets.only(

View File

@ -41,6 +41,7 @@ class PLVideoPlayer extends StatefulWidget {
this.customWidgets,
this.showEposideCb,
this.fullScreenCb,
this.alignment = Alignment.center,
super.key,
});
@ -55,6 +56,7 @@ class PLVideoPlayer extends StatefulWidget {
final List<Widget>? customWidgets;
final Function? showEposideCb;
final Function? fullScreenCb;
final Alignment? alignment;
@override
State<PLVideoPlayer> createState() => _PLVideoPlayerState();
@ -393,6 +395,7 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
key: ValueKey(_.videoFit.value),
controller: videoController,
controls: NoVideoControls,
alignment: widget.alignment!,
pauseUponEnteringBackgroundMode: !enableBackgroundPlay,
resumeUponEnteringForegroundMode: true,
subtitleViewConfiguration: const SubtitleViewConfiguration(