From b60a52f9141b34226360135be5a30440f33d1159 Mon Sep 17 00:00:00 2001 From: Jolie <412895109@qq.com> Date: Mon, 17 Nov 2025 13:11:02 +0800 Subject: [PATCH] =?UTF-8?q?feat(live):=20=E6=B7=BB=E5=8A=A0=E7=9B=B4?= =?UTF-8?q?=E6=92=AD=E9=97=B4=E7=9B=B8=E5=85=B3=E7=BB=84=E4=BB=B6-=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=A4=BC=E7=89=A9=E5=BC=B9=E7=AA=97=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=20(LiveGiftPopup)=EF=BC=8C=E6=94=AF=E6=8C=81=E7=A4=BC?= =?UTF-8?q?=E7=89=A9=E9=80=89=E6=8B=A9=E4=B8=8E=E6=95=B0=E9=87=8F=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20-=20=E6=96=B0=E5=A2=9E=E5=85=85=E5=80=BC=E5=BC=B9?= =?UTF-8?q?=E7=AA=97=E7=BB=84=E4=BB=B6=20(LiveRechargePopup)=EF=BC=8C?= =?UTF-8?q?=E5=8C=85=E5=90=AB=E6=94=AF=E4=BB=98=E9=80=89=E9=A1=B9=E4=B8=8E?= =?UTF-8?q?=E5=8D=8F=E8=AE=AE=E7=A1=AE=E8=AE=A4-=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=9B=B4=E6=92=AD=E9=97=B4=E5=BA=95=E9=83=A8=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=A0=8F=20(LiveRoomActionBar)=EF=BC=8C=E9=9B=86=E6=88=90?= =?UTF-8?q?=E8=81=8A=E5=A4=A9=E8=BE=93=E5=85=A5=E4=B8=8E=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E6=8C=89=E9=92=AE-=20=E6=96=B0=E5=A2=9E=E6=B4=BB=E8=B7=83?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=B1=95=E7=A4=BA=E7=BB=84=E4=BB=B6=20(LiveR?= =?UTF-8?q?oomActiveSpeaker)=20-=20=E6=96=B0=E5=A2=9E=E4=B8=BB=E6=92=AD?= =?UTF-8?q?=E5=B1=95=E7=A4=BA=E5=8C=BA=E7=BB=84=E4=BB=B6=20(LiveRoomAnchor?= =?UTF-8?q?Showcase)=EF=BC=8C=E5=8C=85=E5=90=AB=E4=B8=BB=E6=8C=81=E4=B8=8E?= =?UTF-8?q?=E4=BE=A7=E8=BE=B9=E4=B8=BB=E6=92=AD=E5=8D=A1=E7=89=87=20-=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=81=8A=E5=A4=A9=E6=B6=88=E6=81=AF=E9=A1=B9?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=20(LiveRoomChatItem)=20-=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E7=A4=BC=E7=89=A9=E9=80=89=E9=A1=B9=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=20(LiveRoomGiftItem)=EF=BC=8C=E6=94=AF=E6=8C=81=E9=80=89?= =?UTF-8?q?=E4=B8=AD=E7=8A=B6=E6=80=81=20-=20=E6=96=B0=E5=A2=9E=E5=85=AC?= =?UTF-8?q?=E5=91=8A=E4=B8=8E=E8=81=8A=E5=A4=A9=E9=9D=A2=E6=9D=BF=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=20(LiveRoomNoticeChatPanel)=20-=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=85=85=E5=80=BC=E9=80=89=E9=A1=B9=E7=BB=84=E4=BB=B6=20(LiveR?= =?UTF-8?q?oomPayItem)=EF=BC=8C=E6=94=AF=E6=8C=81=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E4=B8=8E=E9=80=89=E4=B8=AD=E7=8A=B6=E6=80=81=20-=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=BA=A7=E4=BD=8D=E5=88=97=E8=A1=A8=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=20(LiveRoomSeatList)=EF=BC=8C=E5=B1=95=E7=A4=BA=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=BA=A7=E4=BD=8D=E4=B8=8E=E9=BA=A6=E5=85=8B=E9=A3=8E?= =?UTF-8?q?=E7=8A=B6=E6=80=81=20-=20=E6=96=B0=E5=A2=9E=E7=9B=B4=E6=92=AD?= =?UTF-8?q?=E9=97=B4=E9=A1=B6=E9=83=A8=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=20(LiveRoomUserHeader)=EF=BC=8C=E5=8C=85?= =?UTF-8?q?=E5=90=AB=E5=85=B3=E6=B3=A8=E4=B8=8E=E5=85=B3=E9=97=AD=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pages/discover/live_room_page.dart | 1912 +---------------- lib/widget/live/live_gift_popup.dart | 326 +++ lib/widget/live/live_recharge_popup.dart | 227 ++ lib/widget/live/live_room_action_bar.dart | 121 ++ lib/widget/live/live_room_active_speaker.dart | 54 + .../live/live_room_anchor_showcase.dart | 195 ++ lib/widget/live/live_room_chat_item.dart | 44 + lib/widget/live/live_room_gift_item.dart | 72 + .../live/live_room_notice_chat_panel.dart | 53 + lib/widget/live/live_room_pay_item.dart | 152 ++ lib/widget/live/live_room_seat_list.dart | 128 ++ lib/widget/live/live_room_user_header.dart | 128 ++ 12 files changed, 1559 insertions(+), 1853 deletions(-) create mode 100644 lib/widget/live/live_gift_popup.dart create mode 100644 lib/widget/live/live_recharge_popup.dart create mode 100644 lib/widget/live/live_room_action_bar.dart create mode 100644 lib/widget/live/live_room_active_speaker.dart create mode 100644 lib/widget/live/live_room_anchor_showcase.dart create mode 100644 lib/widget/live/live_room_chat_item.dart create mode 100644 lib/widget/live/live_room_gift_item.dart create mode 100644 lib/widget/live/live_room_notice_chat_panel.dart create mode 100644 lib/widget/live/live_room_pay_item.dart create mode 100644 lib/widget/live/live_room_seat_list.dart create mode 100644 lib/widget/live/live_room_user_header.dart diff --git a/lib/pages/discover/live_room_page.dart b/lib/pages/discover/live_room_page.dart index e9c5aa2..c297871 100644 --- a/lib/pages/discover/live_room_page.dart +++ b/lib/pages/discover/live_room_page.dart @@ -2,7 +2,15 @@ import 'package:dating_touchme_app/generated/assets.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; -import 'package:flutter_swiper_null_safety/flutter_swiper_null_safety.dart'; +import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; +import 'package:dating_touchme_app/widget/live/live_room_user_header.dart'; +import 'package:dating_touchme_app/widget/live/live_room_anchor_showcase.dart'; +import 'package:dating_touchme_app/widget/live/live_room_seat_list.dart'; +import 'package:dating_touchme_app/widget/live/live_room_active_speaker.dart'; +import 'package:dating_touchme_app/widget/live/live_room_notice_chat_panel.dart'; +import 'package:dating_touchme_app/widget/live/live_room_action_bar.dart'; +import 'package:dating_touchme_app/widget/live/live_gift_popup.dart'; +import 'package:dating_touchme_app/widget/live/live_recharge_popup.dart'; class LiveRoomPage extends StatefulWidget { final int id; @@ -13,8 +21,6 @@ class LiveRoomPage extends StatefulWidget { } class _LiveRoomPageState extends State { - - String message = ''; final TextEditingController _messageController = TextEditingController(); @@ -45,18 +51,14 @@ class _LiveRoomPageState extends State { final payChecked = ValueNotifier(true); - changeActive(int index){ + changeActive(int index) { activeGift.value = index; - setState(() { - - }); + setState(() {}); } - changePayActive(int index){ + changePayActive(int index) { activePay.value = index; - setState(() { - - }); + setState(() {}); } @override @@ -64,6 +66,32 @@ class _LiveRoomPageState extends State { super.initState(); } + void _showGiftPopup() { + SmartDialog.show( + alignment: Alignment.bottomCenter, + maskColor: TDTheme.of(context).fontGyColor2, + builder: (_) => LiveGiftPopup( + activeGift: activeGift, + giftNum: giftNum, + giftList: giftList, + changeActive: changeActive, + ), + ); + } + + void _showRechargePopup() { + SmartDialog.show( + alignment: Alignment.bottomCenter, + maskColor: TDTheme.of(context).fontGyColor2, + builder: (_) => LiveRechargePopup( + activePay: activePay, + payChecked: payChecked, + payList: payList, + changePayActive: changePayActive, + ), + ); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -101,1859 +129,37 @@ class _LiveRoomPageState extends State { child: SingleChildScrollView( child: Column( children: [ - SizedBox(height: 10.w,), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container ( - height: 40.w, - padding: EdgeInsets.symmetric(horizontal: 3.w), - margin: EdgeInsets.only(left: 10.w), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(40.w)), - color: const Color.fromRGBO(0, 0, 0, .25) - ), - child: Row( - children: [ - Image.asset( - Assets.imagesUserAvatar, - width: 34.w, - height: 34.w, - ), - SizedBox(width: 7.w,), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "开心的橘子", - style: TextStyle( - fontSize: 13.w, - color: Colors.white - ), - ), - Row( - children: [ - Image.asset( - Assets.imagesFireIcon, - width: 10.w, - height: 12.w, - ), - SizedBox(width: 4.w,), - Text( - "1263", - style: TextStyle( - fontSize: 10.w, - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ) - ], - ) - ], - ), - SizedBox(width: 15.w,), - Container( - width: 47.w, - height: 27.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(27.w)), - color: const Color.fromRGBO(253, 43, 84, 1) - ), - child: Center( - child: Text( - "关注", - style: TextStyle( - fontSize: 13.w, - color: Colors.white, - fontWeight: FontWeight.w500, - height: 1 - ), - ), - ), - ) - ], - ), - ), - Container( - width: 30.w, - height: 30.w, - margin: EdgeInsets.only(right: 15.w), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(30.w)), - color: const Color.fromRGBO(0, 0, 0, .3) - ), - child: Center( - child: Image.asset( - Assets.imagesCloseArrow, - width: 14.w, - height: 14.w, - ), - ), - ) - ], - ), - SizedBox(height: 7.w,), - Stack( - children: [ - Container( - width: 177.w, - height: 175.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(9.w)), - color: const Color.fromRGBO(47, 10, 94, 1) - ), - ), - Positioned( - top: 5.w, - left: 5.w, - child: Container( - width: 42.w, - height: 13.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(13.w)), - color: const Color.fromRGBO(142, 20, 186, 1) - ), - child: Center( - child: Text( - "主持人", - style: TextStyle( - fontSize: 9.w, - color: Colors.white - ), - ), - ), - ), - ), - Positioned( - top: 5.w, - right: 5.w, - child: Container( - width: 20.w, - height: 20.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(19.w)), - color: const Color.fromRGBO(0, 0, 0, .3) - ), - child: Center( - child: Image.asset( - Assets.imagesGiftIcon, - width: 19.w, - height: 19.w, - ), - ), - ), - ), - Positioned( - bottom: 5.w, - right: 5.w, - child: Container( - width: 47.w, - height: 20.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(20.w)), - color: Colors.white - ), - child: Center( - child: Text( - "加好友", - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(117, 98, 249, 1) - ), - ), - ), - ), - ) - ], - ), - SizedBox(height: 5.w,), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Stack( - children: [ - Container( - width: 177.w, - height: 175.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.horizontal(left: Radius.circular(18.w)), - color: const Color.fromRGBO(47, 10, 94, 1) - ), - ), - Positioned( - top: 5.w, - right: 5.w, - child: Container( - width: 20.w, - height: 20.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(20.w)), - color: const Color.fromRGBO(0, 0, 0, .3) - ), - child: Center( - child: Image.asset( - Assets.imagesGiftIcon, - width: 19.w, - height: 19.w, - ), - ), - ), - ), - Positioned( - bottom: 5.w, - right: 5.w, - child: Container( - width: 47.w, - height: 20.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(20.w)), - color: Colors.white - ), - child: Center( - child: Text( - "加好友", - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(117, 98, 249, 1) - ), - ), - ), - ), - ), - Positioned( - left: 5.w, - bottom: 5.w, - child: Row( - children: [ - 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, - ), - ), - ), - SizedBox(width: 5.w,), - Text( - "飞翔的企鹅", - style: TextStyle( - fontSize: 11.w, - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ) - ], - ), - ) - ], - ), - Stack( - children: [ - Container( - width: 177.w, - height: 175.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.horizontal(right: Radius.circular(18.w)), - color: const Color.fromRGBO(47, 10, 94, 1) - ), - ), - Positioned( - top: 5.w, - right: 5.w, - child: Container( - width: 20.w, - height: 20.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(19.w)), - color: const Color.fromRGBO(0, 0, 0, .3) - ), - child: Center( - child: Image.asset( - Assets.imagesGiftIcon, - width: 19.w, - height: 19.w, - ), - ), - ), - ), - Positioned( - bottom: 5.w, - right: 5.w, - child: Container( - width: 47.w, - height: 20.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(20.w)), - color: Colors.white - ), - child: Center( - child: Text( - "加好友", - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(117, 98, 249, 1) - ), - ), - ), - ), - ), - Positioned( - left: 5.w, - bottom: 5.w, - child: Row( - children: [ - 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.imagesMicOpen, - width: 10.w, - height: 11.w, - ), - ), - ), - SizedBox(width: 5.w,), - Text( - "飞翔的企鹅", - style: TextStyle( - fontSize: 11.w, - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ) - ], - ), - ) - ], - ), - ], + SizedBox(height: 10.w), + const LiveRoomUserHeader( + userName: '开心的橘子', + popularityText: '1263', ), - SizedBox(height: 5.w,), - Container( - width: 375.w, - height: 55.w, - padding: EdgeInsets.symmetric(horizontal: 6.w), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(9.w)), - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, // 135° 对应 topLeft → bottomRight - colors: [ - Color.fromRGBO(46, 19, 79, 1), // 0% - Color.fromRGBO(61, 67, 130, 1), // 31.53% - Color.fromRGBO(64, 23, 115, 1), // 72.09% - Color.fromRGBO(26, 28, 86, 1), // 100% - ], - stops: [0.0, 0.3153, 0.7209, 1.0], // 对应 CSS 百分比位置 - ), - border: Border.all(width: 1, color: const Color.fromRGBO(117, 102, 255, 1)) - ), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - children: [ - Container( - margin: EdgeInsets.symmetric(horizontal: 7.w), - child: Stack( - children: [ - Image.asset( - Assets.imagesSeat, - width: 35.w, - height: 35.w, - ), - Positioned( - bottom: 0, - left: 3.w, - child: Container( - width: 23.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4.w)), - color: const Color.fromRGBO(0, 0, 0, .65) - ), - child: Row( - children: [ - Expanded( - child: Center( - child: Text( - "1", - style: TextStyle( - fontSize: 8.w, - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ), - ), - ), - Container( - width: 12.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(24.w)), - gradient: LinearGradient( - begin: Alignment.centerLeft, // 左侧开始 - end: Alignment.centerRight, // 右侧结束 - colors: [ - Color.fromRGBO(131, 89, 255, 1), // 紫色 - Color.fromRGBO(61, 138, 224, 1), // 蓝色 - ], - ), - ), - child: Center( - child: Image.asset( - Assets.imagesMicClose, - width: 6.w, - height: 6.w, - ), - ), - ) - ], - ), - ), - ) - ], - ), - ), - Container( - margin: EdgeInsets.symmetric(horizontal: 7.w), - child: Stack( - children: [ - Image.asset( - Assets.imagesSeat, - width: 35.w, - height: 35.w, - ), - Positioned( - bottom: 0, - left: 3.w, - child: Container( - width: 23.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4.w)), - color: const Color.fromRGBO(0, 0, 0, .65) - ), - child: Row( - children: [ - Expanded( - child: Center( - child: Text( - "1", - style: TextStyle( - fontSize: 8.w, - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ), - ), - ), - Container( - width: 12.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(24.w)), - gradient: LinearGradient( - begin: Alignment.centerLeft, // 左侧开始 - end: Alignment.centerRight, // 右侧结束 - colors: [ - Color.fromRGBO(131, 89, 255, 1), // 紫色 - Color.fromRGBO(61, 138, 224, 1), // 蓝色 - ], - ), - ), - child: Center( - child: Image.asset( - Assets.imagesMicClose, - width: 6.w, - height: 7.w, - ), - ), - ) - ], - ), - ), - ) - ], - ), - ), - Container( - margin: EdgeInsets.symmetric(horizontal: 7.w), - child: Stack( - children: [ - Image.asset( - Assets.imagesSeat, - width: 35.w, - height: 35.w, - ), - Positioned( - bottom: 0, - left: 3.w, - child: Container( - width: 28.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4.w)), - color: const Color.fromRGBO(0, 0, 0, .65) - ), - child: Row( - children: [ - Expanded( - child: Center( - child: Text( - "1", - style: TextStyle( - fontSize: 8.w, - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ), - ), - ), - Container( - width: 12.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(12.w)), - gradient: LinearGradient( - begin: Alignment.centerLeft, // 左侧开始 - end: Alignment.centerRight, // 右侧结束 - colors: [ - Color.fromRGBO(131, 89, 255, 1), // 紫色 - Color.fromRGBO(61, 138, 224, 1), // 蓝色 - ], - ), - ), - child: Center( - child: Image.asset( - Assets.imagesMicClose, - width: 6.w, - height: 7.w, - ), - ), - ) - ], - ), - ), - ) - ], - ), - ), - Container( - margin: EdgeInsets.symmetric(horizontal: 7.w), - child: Stack( - children: [ - Image.asset( - Assets.imagesSeat, - width: 35.w, - height: 35.w, - ), - Positioned( - bottom: 0, - left: 3.w, - child: Container( - width: 28.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4.w)), - color: const Color.fromRGBO(0, 0, 0, .65) - ), - child: Row( - children: [ - Expanded( - child: Center( - child: Text( - "1", - style: TextStyle( - fontSize: 8.w, - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ), - ), - ), - Container( - width: 12.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(12.w)), - gradient: LinearGradient( - begin: Alignment.centerLeft, // 左侧开始 - end: Alignment.centerRight, // 右侧结束 - colors: [ - Color.fromRGBO(131, 89, 255, 1), // 紫色 - Color.fromRGBO(61, 138, 224, 1), // 蓝色 - ], - ), - ), - child: Center( - child: Image.asset( - Assets.imagesMicClose, - width: 6.w, - height: 7.w, - ), - ), - ) - ], - ), - ), - ) - ], - ), - ), - Container( - margin: EdgeInsets.symmetric(horizontal: 7.w), - child: Stack( - children: [ - Image.asset( - Assets.imagesSeat, - width: 35.w, - height: 35.w, - ), - Positioned( - bottom: 0, - left: 3.w, - child: Container( - width: 28.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4.w)), - color: const Color.fromRGBO(0, 0, 0, .65) - ), - child: Row( - children: [ - Expanded( - child: Center( - child: Text( - "1", - style: TextStyle( - fontSize: 8.w, - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ), - ), - ), - Container( - width: 12.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(12.w)), - gradient: LinearGradient( - begin: Alignment.centerLeft, // 左侧开始 - end: Alignment.centerRight, // 右侧结束 - colors: [ - Color.fromRGBO(131, 89, 255, 1), // 紫色 - Color.fromRGBO(61, 138, 224, 1), // 蓝色 - ], - ), - ), - child: Center( - child: Image.asset( - Assets.imagesMicClose, - width: 6.w, - height: 7.w, - ), - ), - ) - ], - ), - ), - ) - ], - ), - ), - Container( - margin: EdgeInsets.symmetric(horizontal: 7.w), - child: Stack( - children: [ - Image.asset( - Assets.imagesSeat, - width: 35.w, - height: 35.w, - ), - Positioned( - bottom: 0, - left: 3.w, - child: Container( - width: 28.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4.w)), - color: const Color.fromRGBO(0, 0, 0, .65) - ), - child: Row( - children: [ - Expanded( - child: Center( - child: Text( - "1", - style: TextStyle( - fontSize: 8.w, - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ), - ), - ), - Container( - width: 12.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(12.w)), - gradient: LinearGradient( - begin: Alignment.centerLeft, // 左侧开始 - end: Alignment.centerRight, // 右侧结束 - colors: [ - Color.fromRGBO(131, 89, 255, 1), // 紫色 - Color.fromRGBO(61, 138, 224, 1), // 蓝色 - ], - ), - ), - child: Center( - child: Image.asset( - Assets.imagesMicClose, - width: 6.w, - height: 7.w, - ), - ), - ) - ], - ), - ), - ) - ], - ), - ), - Container( - margin: EdgeInsets.symmetric(horizontal: 7.w), - child: Stack( - children: [ - Image.asset( - Assets.imagesSeat, - width: 35.w, - height: 35.w, - ), - Positioned( - bottom: 0, - left: 3.w, - child: Container( - width: 28.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(4.w)), - color: const Color.fromRGBO(0, 0, 0, .65) - ), - child: Row( - children: [ - Expanded( - child: Center( - child: Text( - "1", - style: TextStyle( - fontSize: 8.w, - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ), - ), - ), - Container( - width: 12.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(12.w)), - gradient: LinearGradient( - begin: Alignment.centerLeft, // 左侧开始 - end: Alignment.centerRight, // 右侧结束 - colors: [ - Color.fromRGBO(131, 89, 255, 1), // 紫色 - Color.fromRGBO(61, 138, 224, 1), // 蓝色 - ], - ), - ), - child: Center( - child: Image.asset( - Assets.imagesMicClose, - width: 6.w, - height: 7.w, - ), - ), - ) - ], - ), - ), - ) - ], - ), - ), - ], - ), - ), - ), - SizedBox(height: 5.w,), - 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, - ), - ), - ), - 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, - ), - ), - ), - ) - ], - ) - ], - ), - SizedBox(height: 9.w,), - Container( - height: 230.w, - padding: EdgeInsets.only( - left: 13.w, - right: 9.w - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: SingleChildScrollView( - child: Column( - children: [ - Text( - "欢迎来到直播间!严禁未成年人直播或礼物消费。严禁违法违规、低俗色情、吸烟酗酒、人身伤害等直播内容。理性消费如主播在直播中以不当方式诱导消费,请谨慎辨别。切勿私下交易,以防人身财产损失,谨防网络诈骗。", - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(155, 138, 246, 1) - ), - ), - SizedBox(height: 15.w,), - ChatItem(), - ChatItem(), - ChatItem(), - ChatItem(), - ChatItem(), - ChatItem(), - ChatItem(), - ChatItem(), - ChatItem(), - ], - ), - ), - ), - SizedBox(width: 18.w,), - Image.asset( - Assets.imagesAd, - width: 73.w, - fit: BoxFit.cover, - ) - ], - ), - ), - SizedBox(height: 17.w,), + SizedBox(height: 7.w), + const LiveRoomAnchorShowcase(), + SizedBox(height: 5.w), + const LiveRoomSeatList(), + SizedBox(height: 5.w), + const LiveRoomActiveSpeaker(), + SizedBox(height: 9.w), + const LiveRoomNoticeChatPanel(), + SizedBox(height: 17.w), ], ), ), ), - Row( - children: [ - Container( - margin: EdgeInsets.only(left: 16.w), - child: InkWell( - onTap: (){ - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: (context) { - return Material( - child: ValueListenableBuilder( - valueListenable: activeGift, - builder: (context, active, _) { - return Container( - color: const Color.fromRGBO(41, 31, 61, 1), - height: 363.w, - child: Column( - children: [ - Container( - height: 53.w, - padding: EdgeInsets.symmetric(horizontal: 10.w), - child: Row( - children: [ - Row( - children: [ - Text( - "送给: ", - style: TextStyle( - fontSize: 13.w, - color: Colors.white - ), - ), - SizedBox(width: 6.w,), - Stack( - children: [ - ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(68.w)), - child: Container( - width: 34.w, - height: 34.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(68.w)), - border: Border.all(width: 2, color: const Color.fromRGBO(117, 98, 249, 1)) - ), - child: Image.asset( - Assets.imagesUserAvatar, - width: 32.w, - height: 32.w, - ), - ), - ), - Positioned( - bottom: 0, - right: 2.w, - child: Container( - width: 12.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(12.w)), - color: const Color.fromRGBO(117, 98, 249, 1) - ), - child: Center( - child: Image.asset( - Assets.imagesCheck, - width: 6.w, - height: 4.w, - ), - ), - ), - ) - ], - ), - SizedBox(width: 10.w,), - Stack( - children: [ - ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(34.w)), - child: Container( - width: 34.w, - height: 34.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(34.w)), - border: Border.all(width: 2, color: const Color.fromRGBO(117, 98, 249, 1)) - ), - child: Image.asset( - Assets.imagesUserAvatar, - width: 32.w, - height: 32.w, - ), - ), - ), - Positioned( - bottom: 0, - right: 2.w, - child: Container( - width: 12.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(12.w)), - color: const Color.fromRGBO(117, 98, 249, 1) - ), - child: Center( - child: Image.asset( - Assets.imagesCheck, - width: 6.w, - height: 4.w, - ), - ), - ), - ) - ], - ), - SizedBox(width: 10.w,), - Stack( - children: [ - ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(34.w)), - child: Container( - width: 34.w, - height: 34.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(34.w)), - border: Border.all(width: 1, color: const Color.fromRGBO(117, 98, 249, 1)) - ), - child: Image.asset( - Assets.imagesUserAvatar, - width: 34.w, - height: 34.w, - ), - ), - ), - Positioned( - bottom: 0, - right: 2.w, - child: Container( - width: 12.w, - height: 12.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(12.w)), - color: const Color.fromRGBO(117, 98, 249, 1) - ), - child: Center( - child: Image.asset( - Assets.imagesCheck, - width: 6.w, - height: 4.w, - ), - ), - ), - ) - ], - ), - SizedBox(width: 10.w,), - ], - ), - Container( - width: 63.w, - height: 30.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(30.w)), - color: const Color.fromRGBO(117, 98, 249, 1) - ), - child: Center( - child: Text( - "全选", - style: TextStyle( - fontSize: 13.w, - color: Colors.white - ), - ), - ), - ) - ], - ), - ), - Expanded( - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.vertical(top: Radius.circular(9.w)), - color: const Color.fromRGBO(22, 19, 28, 1) - ), - child: Column( - children: [ - Container( - height: 47.w, - padding: EdgeInsets.only(left: 29.w), - child: Row( - children: [ - Text( - "互动", - style: TextStyle( - fontSize: 13.w, - color: const Color.fromRGBO(144, 144, 144, 1) - ), - ), - SizedBox(width: 40.w,), - Text( - "礼物", - style: TextStyle( - fontSize: 13.w, - color: Colors.white, - fontWeight: FontWeight.w700 - ), - ), - ], - ), - ), - Expanded( - child: Swiper( - autoplay: false, - itemCount: 6, - loop: true, - pagination: const SwiperPagination( - alignment: Alignment.bottomCenter, - builder: TDSwiperDotsPagination( - color: Color.fromRGBO(144, 144, 144, 1), - activeColor: Color.fromRGBO(77, 77, 77, 1), - )), - itemBuilder: (BuildContext context, int index) { - return Align( - alignment: Alignment.topCenter, - child: Wrap( - children: [ - ...giftList.asMap().entries.map((entry){ - return GiftItem(item: entry.value, active: active ?? 0, index: entry.key, changeActive: changeActive); - }), - ], - ), - ); - }, - ), - ), - Container( - padding: EdgeInsets.symmetric(horizontal: 10.w), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Image.asset( - Assets.imagesRoseGift, - width: 21.w, - height: 21.w, - ), - SizedBox(width: 8.w,), - Text( - "9", - style: TextStyle( - fontSize: 13.w, - color: Colors.white - ), - ), - SizedBox(width: 12.w,), - Image.asset( - Assets.imagesRoseGift, - width: 68.w, - height: 33.w, - ), - ], - ) , - ValueListenableBuilder( - valueListenable: giftNum, - builder: (context, num, _) { - return Row( - children: [ - // TDStepper( - // theme: TDStepperTheme.filled, - // value: giftNum, - // min: 1, - // onChange: (e){ - // giftNum = e; - // }, - // ), - InkWell( - onTap: (){ - if(giftNum.value <= 1) return; - giftNum.value -= 1; - setState(() { - - }); - }, - child: Container( - width: 14.w, - height: 14.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(14.w)), - color: Color.fromRGBO(117, 98, 249, giftNum.value <= 1 ? 0 : 1), - border: Border.all(width: 1, color: Color.fromRGBO(117, 98, 249, 1)) - ), - child: Center( - child: Text( - "-", - style: TextStyle( - fontSize: 13.w, - color: giftNum.value <= 1 ? Color.fromRGBO(117, 98, 249, 1) : Colors.white, - height: 1 - ), - ), - ), - ), - ), - SizedBox( - width: 23.w, - child: Center( - child: Text( - "$num", - style: TextStyle( - fontSize: 13.w, - color: Colors.white - ), - ), - ), - ), - InkWell( - onTap: (){ - giftNum.value += 1; - setState(() { - - }); - }, - child: Container( - width: 14.w, - height: 14.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(14.w)), - color: Color.fromRGBO(117, 98, 249, 1) - ), - child: Center( - child: Text( - "+", - style: TextStyle( - fontSize: 13.w, - color: Colors.white, - height: 1 - ), - ), - ), - ), - ), - SizedBox(width: 9.w,), - Container( - width: 63.w, - height: 30.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(30.w)), - gradient: LinearGradient( - begin: Alignment.centerLeft, // 左侧开始 - end: Alignment.centerRight, // 右侧结束(90度) - colors: [ - Color.fromRGBO(61, 138, 224, 1), // 蓝色 - Color.fromRGBO(131, 89, 255, 1), // 紫色 - ], - ), - ), - child: Center( - child: Text( - "赠送", - style: TextStyle( - fontSize: 13.w, - color: Colors.white - ), - ), - ), - ) - ], - ); - }), - - ], - ), - ) - ], - ), - ), - ) - ], - ), - ); - } - ), - ); - })); - }, - child: Container( - width: 38.w, - height: 38.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(38.w)), - color: const Color.fromRGBO(0, 0, 0, .3) - ), - child: Center( - child: Image.asset( - Assets.imagesGiftIcon, - width: 28.w, - height: 28.w, - ), - ), - ), - ), - ), - SizedBox(width: 9.w,), - Container( - width: 205.w, - height: 38.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(38.w)), - color: const Color.fromRGBO(0, 0, 0, .3) - ), - child: TextField( - controller: _messageController, - keyboardType: TextInputType.number, - style: TextStyle( - fontSize: ScreenUtil().setWidth(14), - height: 1, - color: Colors.white - ), - decoration: InputDecoration( - contentPadding: EdgeInsets.symmetric( - vertical: 0, - horizontal: 37.w - ), - hintText: "聊点什么吧~", - hintStyle: TextStyle( - color: const Color.fromRGBO(144, 144, 144, 1) - ), - border: const OutlineInputBorder( - borderSide: BorderSide.none, // 这将移除边框 // 可选:设置圆角 - ), - // 如果你希望聚焦时和未聚焦时都没有边框,也可以设置 focusedBorder 和 enabledBorder - focusedBorder: const OutlineInputBorder( - borderSide: BorderSide.none, - borderRadius: BorderRadius.all(Radius.circular(4.0)), - ), - enabledBorder: const OutlineInputBorder( - borderSide: BorderSide.none, - borderRadius: BorderRadius.all(Radius.circular(4.0)), - ), - ), - onChanged: (value){ - message = value; - }, - ), - ), - SizedBox(width: 8.w,), - Container( - width: 38.w, - height: 38.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(38.w)), - color: const Color.fromRGBO(0, 0, 0, .3) - ), - child: Center( - child: Image.asset( - Assets.imagesArrowR, - width: 16.w, - height: 16.w, - ), - ), - ), - SizedBox(width: 8.w,), - InkWell( - onTap: (){ - Navigator.of(context).push(TDSlidePopupRoute( - modalBarrierColor: TDTheme.of(context).fontGyColor2, - slideTransitionFrom: SlideTransitionFrom.bottom, - builder: (context) { - return ClipRRect( - borderRadius: BorderRadius.vertical(top: Radius.circular(9.w)), - child: ValueListenableBuilder( - valueListenable: activePay, - builder: (context, active, _){ - return Material( - child: Container( - color: Colors.white, - height: 440.w, - padding: EdgeInsets.symmetric(horizontal: 10.w), - child: ValueListenableBuilder( - valueListenable: payChecked, - builder: (context, payCheckedV, _) { - return Column( - children: [ - Container( - height: 48.w, - padding: EdgeInsets.symmetric(horizontal: 8.w), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - InkWell( - onTap: (){ - Navigator.maybePop(context); - }, - child: Icon( - Icons.close, - size: 14.w, - color: const Color.fromRGBO(114, 114, 114, 1), - ), - ), - Text( - "玫瑰充值", - style: TextStyle( - fontSize: 17.w, - color: const Color.fromRGBO(51, 51, 51, 1), - fontWeight: FontWeight.w500 - ), - ), - Icon( - Icons.close, - size: 14.w, - color: Colors.transparent, - ), - ], - ), - ), - Container( - padding: EdgeInsets.symmetric(horizontal: 8.w), - margin: EdgeInsets.only(bottom: 15.w), - child: Row( - children: [ - Text( - "余额:9玫瑰", - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(144, 144, 144, 1), - fontWeight: FontWeight.w500 - ), - ) - ], - ), - ), - Wrap( - spacing: 7.w, - runSpacing: 7.w, - children: [ - ...payList.asMap().entries.map((entry){ - return PayItem(item: entry.value, active: active ?? 0, index: entry.key, changeActive: changePayActive); - }), - ], - ), - Container( - height: 1, - margin: EdgeInsets.only( - top: 10.w, - bottom: 15.w - ), - color: const Color.fromRGBO(219, 219, 219, 1), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Image.asset( - Assets.imagesAliPay, - width: 17.w, - height: 17.w, - ), - SizedBox(width: 6.w,), - Text( - "支付宝支付", - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(51, 51, 51, 1), - fontWeight: FontWeight.w500 - ), - ) - ], - ), - Checkbox( - value: payCheckedV, - onChanged: (value) { - payChecked.value = true; - setState(() { - - }); - }, - activeColor: const Color.fromRGBO(117, 98, 249, 1), - side: const BorderSide(color: Colors.grey), - shape: const CircleBorder(), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - ], - ), - SizedBox(height: 10.w,), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Image.asset( - Assets.imagesWechatPay, - width: 17.w, - height: 17.w, - ), - SizedBox(width: 6.w,), - Text( - "支付宝支付", - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(51, 51, 51, 1), - fontWeight: FontWeight.w500 - ), - ) - ], - ), - Checkbox( - value: !payCheckedV, - onChanged: (value) { - payChecked.value = false; - setState(() { - - }); - }, - activeColor: const Color.fromRGBO(117, 98, 249, 1), - side: const BorderSide(color: Colors.grey), - shape: const CircleBorder(), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - ), - ], - ), - SizedBox(height: 8.w,), - Row( - children: [ - RichText( - text: TextSpan( - style: TextStyle( - fontSize: 11.w, - fontWeight: FontWeight.w500 - ), - children: const [ - TextSpan( - text: "充值既代表同意", - style: TextStyle( - color: Color.fromRGBO(189, 189, 189, 1) - ) - ), - TextSpan( - text: "《动我充值协议》", - style: TextStyle( - color: Color.fromRGBO(71, 123, 255, 1) - ) - ), - TextSpan( - text: "和隐私政策", - style: TextStyle( - color: Color.fromRGBO(189, 189, 189, 1) - ) - ), - ] - ), - ) - ], - ), - SizedBox(height: 14.w,), - Container( - width: 325.w, - height: 45.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(45.w)), - gradient: LinearGradient( - begin: Alignment.centerLeft, // 0%:左边开始 - end: Alignment.centerRight, // 100%:右边结束 - colors: [ - Color.fromRGBO(131, 89, 255, 1), // 紫色 - Color.fromRGBO(77, 127, 231, 1), // 中间淡蓝 - Color.fromRGBO(61, 138, 224, 1), // 右侧深蓝 - ], - stops: [0.0, 0.7753, 1.0], // 对应 CSS 百分比:0%、77.53%、100% - ), - ), - child: Center( - child: Text( - "立即充值", - style: TextStyle( - fontSize: 13.w, - color: Colors.white, - fontWeight: FontWeight.w500 - ), - ), - ), - ) - ], - ); - }, - ), - - - ), - ); - } - ), - - - - - ); - })); - }, - child: Container( - width: 38.w, - height: 38.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(38.w)), - gradient: LinearGradient( - // 144° ≈ 从左上角稍偏右下方向 - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - Color.fromRGBO(255, 43, 110, 1), // 起始色 - Color.fromRGBO(255, 52, 26, 1), // 结束色 - ], - ), - ), - child: Center( - child: Image.asset( - Assets.imagesRoseWhite, - width: 14.w, - height: 25.w, - ), - ), - ), - ), - ], - ) - ], - ), - ) - ], - ), - ); - } -} - -class ChatItem extends StatelessWidget { - const ChatItem({super.key}); - - @override - Widget build(BuildContext context) { - return Container( - width: 260.w, - margin: EdgeInsets.only(bottom: 15.w), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Image.asset( - Assets.imagesUserAvatar, - width: 25.w, - height: 25.w, - ), - SizedBox(width: 10.w,), - SizedBox( - width: 224.w, - child: RichText( - text: TextSpan( - children: [ - TextSpan( - text: "沙发沙发:", - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(155, 138, 246, 1) - ) - ), - TextSpan( - text: "大家好啊!大家好啊!大家好啊!大家好啊!大家好啊!大家好啊!大家好啊!大家好啊!大家好啊!", - style: TextStyle( - fontSize: 11.w, - color: Colors.white - ) - ) - ] - ), - ), - ) - ], - ), - ); - } -} - -class GiftItem extends StatefulWidget { - final Map item; - final int active; - final int index; - final void Function(int) changeActive; - const GiftItem({super.key, required this.item, required this.active, required this.index, required this.changeActive, }); - - @override - State createState() => _GiftItemState(); -} - -class _GiftItemState extends State { - @override - Widget build(BuildContext context) { - return InkWell( - onTap: (){ - widget.changeActive(widget.index); - }, - child: Container( - width: 83.w, - height: 94.w, - padding: EdgeInsets.only(top: 10.w), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(9.w)), - color: Color.fromRGBO(117, 98, 249, widget.active == widget.index ? .2 : 0), - border: Border.all(width: 1, color: Color.fromRGBO(117, 98, 249, widget.active == widget.index ? 1 : 0)) - ), - child: Column( - children: [ - Image.asset( - widget.item["icon"], - width: 41.w, - height: 41.w, - ), - SizedBox(height: 7.w,), - Text( - widget.item["title"], - style: TextStyle( - fontSize: 11.w, - color: Colors.white - ), - ), - SizedBox(height: 1.w,), - Text( - "${widget.item["price"]}支", - style: TextStyle( - fontSize: 7.w, - color: const Color.fromRGBO(144, 144, 144, 1) - ), - ), - ], - ), - ), - ); - } -} - -class PayItem extends StatefulWidget { - final Map item; - final int active; - final int index; - final void Function(int) changeActive; - const PayItem({super.key, required this.item, required this.active, required this.index, required this.changeActive, }); - - @override - State createState() => _PayItemState(); -} - -class _PayItemState extends State { - @override - Widget build(BuildContext context) { - return InkWell( - onTap: (){ - widget.changeActive(widget.index); - }, - child: Stack( - children: [ - Container( - width: 113.w, - height: 55.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(9.w)), - color: widget.active == widget.index ? const Color.fromRGBO(239, 19, 46, .05) : const Color.fromRGBO(247, 247, 247, 1), - border: widget.active == widget.index ? Border.all(width: 1, color: const Color.fromRGBO(239, 19, 46, 1)) : null - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - RichText( - text: TextSpan( - children: [ - TextSpan( - text: "${widget.item["num"]}", - style: TextStyle( - fontSize: 17.w, - color: const Color.fromRGBO(51, 51, 51, 1), - fontWeight: FontWeight.w700 - ), - ), - TextSpan( - text: "玫瑰", - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(51, 51, 51, 1), - fontWeight: FontWeight.w500 - ), - ) - ] - ), + LiveRoomActionBar( + messageController: _messageController, + onMessageChanged: (value) { + message = value; + }, + onGiftTap: _showGiftPopup, + onChargeTap: _showRechargePopup, ), - Text( - "${widget.item["price"]}元", - style: TextStyle( - fontSize: 11.w, - color: const Color.fromRGBO(144, 144, 144, 144), - fontWeight: FontWeight.w500 - ), - ) ], ), ), - if(widget.item["hasTag"]) Positioned( - top: 0, - left: 0, - child: Container( - width: 53.w, - height: 11.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(9.w), - bottomRight: Radius.circular(9.w), - ), - color: widget.active == widget.index ? null :const Color.fromRGBO(238, 24, 50, .1), - gradient: widget.active == widget.index ? LinearGradient( - begin: Alignment.centerLeft, // 对应 0% - end: Alignment.centerRight, // 对应 100% - colors: [ - Color.fromRGBO(238, 24, 50, 1), // #EE1832 深红 - Color.fromRGBO(250, 101, 64, 1), // #FA6540 橙红 - Color.fromRGBO(255, 131, 69, 1), // #FF8345 浅橙 - ], - stops: [0.0, 0.7216, 1.0], // 对应 CSS 中的百分比位置 - ) : null, - ), - child: Center( - child: Text( - "送新人大礼包", - style: TextStyle( - fontSize: 6.w, - color: widget.active == widget.index ? Colors.white : const Color.fromRGBO(237, 23, 50, 1), - fontWeight: FontWeight.w500 - ), - ), - ), - ), - ), - if(widget.active == widget.index) Positioned( - right: 0, - bottom: 0, - child: Container( - width: 17.w, - height: 13.w, - decoration: BoxDecoration( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(9.w), - bottomRight: Radius.circular(9.w), - ), - color: const Color.fromRGBO(239, 19, 46, 1) - ), - child: Center( - child: Image.asset( - Assets.imagesCheck, - width: 6.w, - height: 4.w, - ), - ), - ), - ) ], ), ); } } - diff --git a/lib/widget/live/live_gift_popup.dart b/lib/widget/live/live_gift_popup.dart new file mode 100644 index 0000000..c0376dc --- /dev/null +++ b/lib/widget/live/live_gift_popup.dart @@ -0,0 +1,326 @@ +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:dating_touchme_app/widget/live/live_room_gift_item.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:flutter_swiper_null_safety/flutter_swiper_null_safety.dart'; +import 'package:tdesign_flutter/tdesign_flutter.dart'; + +class LiveGiftPopup extends StatelessWidget { + const LiveGiftPopup({ + super.key, + required this.activeGift, + required this.giftNum, + required this.giftList, + required this.changeActive, + }); + + final ValueNotifier activeGift; + final ValueNotifier giftNum; + final List giftList; + final void Function(int) changeActive; + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: Container( + color: const Color.fromRGBO(41, 31, 61, 1), + height: 363.w, + child: Column( + children: [ + _buildHeader(), + Expanded( + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.vertical(top: Radius.circular(9.w)), + color: const Color.fromRGBO(22, 19, 28, 1), + ), + child: Column( + children: [ + _buildTab(), + _buildGiftSwiper(), + _buildBottomBar(), + ], + ), + ), + ), + ], + ), + ), + ); + } + + Widget _buildHeader() { + return Container( + height: 53.w, + padding: EdgeInsets.symmetric(horizontal: 10.w), + child: Row( + children: [ + Row( + children: [ + Text( + "送给: ", + style: TextStyle(fontSize: 13.w, color: Colors.white), + ), + SizedBox(width: 6.w), + ...List.generate(3, (index) { + return Padding( + padding: EdgeInsets.only(right: 10.w), + child: Stack( + children: [ + ClipRRect( + borderRadius: BorderRadius.all( + Radius.circular(index == 0 ? 68.w : 34.w), + ), + child: Container( + width: 34.w, + height: 34.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(index == 0 ? 68.w : 34.w), + ), + border: Border.all( + width: index == 0 ? 2 : 1, + color: const Color.fromRGBO(117, 98, 249, 1), + ), + ), + child: Image.asset( + Assets.imagesUserAvatar, + width: 32.w, + height: 32.w, + ), + ), + ), + Positioned( + bottom: 0, + right: 2.w, + child: Container( + width: 12.w, + height: 12.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(12.w)), + color: const Color.fromRGBO(117, 98, 249, 1), + ), + child: Center( + child: Image.asset( + Assets.imagesCheck, + width: 6.w, + height: 4.w, + ), + ), + ), + ), + ], + ), + ); + }), + ], + ), + Container( + width: 63.w, + height: 30.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(30.w)), + color: const Color.fromRGBO(117, 98, 249, 1), + ), + child: Center( + child: Text( + "全选", + style: TextStyle(fontSize: 13.w, color: Colors.white), + ), + ), + ), + ], + ), + ); + } + + Widget _buildTab() { + return Container( + height: 47.w, + padding: EdgeInsets.only(left: 29.w), + child: Row( + children: [ + Text( + "互动", + style: TextStyle( + fontSize: 13.w, + color: const Color.fromRGBO(144, 144, 144, 1), + ), + ), + SizedBox(width: 40.w), + Text( + "礼物", + style: TextStyle( + fontSize: 13.w, + color: Colors.white, + fontWeight: FontWeight.w700, + ), + ), + ], + ), + ); + } + + Widget _buildGiftSwiper() { + return Expanded( + child: ValueListenableBuilder( + valueListenable: activeGift, + builder: (context, active, _) { + return Swiper( + autoplay: false, + itemCount: 6, + loop: true, + pagination: const SwiperPagination( + alignment: Alignment.bottomCenter, + builder: TDSwiperDotsPagination( + color: Color.fromRGBO(144, 144, 144, 1), + activeColor: Color.fromRGBO(77, 77, 77, 1), + ), + ), + itemBuilder: (context, index) { + return Align( + alignment: Alignment.topCenter, + child: Wrap( + children: [ + ...giftList.asMap().entries.map( + (entry) => LiveRoomGiftItem( + item: entry.value, + active: active ?? 0, + index: entry.key, + changeActive: changeActive, + ), + ), + ], + ), + ); + }, + ); + }, + ), + ); + } + + Widget _buildBottomBar() { + return Container( + padding: EdgeInsets.symmetric(horizontal: 10.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Image.asset( + Assets.imagesRoseGift, + width: 21.w, + height: 21.w, + ), + SizedBox(width: 8.w), + Text( + "9", + style: TextStyle(fontSize: 13.w, color: Colors.white), + ), + SizedBox(width: 12.w), + Image.asset( + Assets.imagesRoseGift, + width: 68.w, + height: 33.w, + ), + ], + ), + ValueListenableBuilder( + valueListenable: giftNum, + builder: (context, num, _) { + return Row( + children: [ + _buildAdjustButton( + label: "-", + enabled: num > 1, + onTap: () { + if (giftNum.value <= 1) return; + giftNum.value -= 1; + }, + ), + SizedBox( + width: 23.w, + child: Center( + child: Text( + "$num", + style: TextStyle(fontSize: 13.w, color: Colors.white), + ), + ), + ), + _buildAdjustButton( + label: "+", + enabled: true, + onTap: () { + giftNum.value += 1; + }, + ), + SizedBox(width: 9.w), + Container( + width: 63.w, + height: 30.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(30.w)), + gradient: const LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Color.fromRGBO(61, 138, 224, 1), + Color.fromRGBO(131, 89, 255, 1), + ], + ), + ), + child: Center( + child: Text( + "赠送", + style: TextStyle(fontSize: 13.w, color: Colors.white), + ), + ), + ), + ], + ); + }, + ), + ], + ), + ); + } + + Widget _buildAdjustButton({ + required String label, + required bool enabled, + required VoidCallback onTap, + }) { + return InkWell( + onTap: enabled ? onTap : null, + child: Container( + width: 14.w, + height: 14.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(14.w)), + color: enabled + ? const Color.fromRGBO(117, 98, 249, 1) + : Colors.transparent, + border: Border.all( + width: 1, + color: const Color.fromRGBO(117, 98, 249, 1), + ), + ), + child: Center( + child: Text( + label, + style: TextStyle( + fontSize: 13.w, + color: enabled + ? Colors.white + : const Color.fromRGBO(117, 98, 249, 1), + height: 1, + ), + ), + ), + ), + ); + } +} + diff --git a/lib/widget/live/live_recharge_popup.dart b/lib/widget/live/live_recharge_popup.dart new file mode 100644 index 0000000..d672031 --- /dev/null +++ b/lib/widget/live/live_recharge_popup.dart @@ -0,0 +1,227 @@ +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:dating_touchme_app/widget/live/live_room_pay_item.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class LiveRechargePopup extends StatelessWidget { + const LiveRechargePopup({ + super.key, + required this.activePay, + required this.payChecked, + required this.payList, + required this.changePayActive, + }); + + final ValueNotifier activePay; + final ValueNotifier payChecked; + final List payList; + final void Function(int) changePayActive; + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: Container( + color: Colors.white, + height: 440.w, + padding: EdgeInsets.symmetric(horizontal: 10.w), + child: Column( + children: [ + _buildHeader(context), + _buildBalanceInfo(), + _buildPayOptions(), + _buildAgreementRow(), + SizedBox(height: 23.w), + _buildSubmitButton(), + ], + ), + ), + ); + } + + Widget _buildHeader(BuildContext context) { + return Container( + height: 48.w, + padding: EdgeInsets.symmetric(horizontal: 8.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + onTap: () => Navigator.maybePop(context), + child: Icon( + Icons.close, + size: 14.w, + color: const Color.fromRGBO(114, 114, 114, 1), + ), + ), + Text( + "玫瑰充值", + style: TextStyle( + fontSize: 17.w, + color: const Color.fromRGBO(51, 51, 51, 1), + fontWeight: FontWeight.w500, + ), + ), + Icon( + Icons.close, + size: 14.w, + color: Colors.transparent, + ), + ], + ), + ); + } + + Widget _buildBalanceInfo() { + return Container( + padding: EdgeInsets.symmetric(horizontal: 8.w), + margin: EdgeInsets.only(bottom: 15.w), + child: Row( + children: [ + Text( + "余额:9玫瑰", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(144, 144, 144, 1), + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ); + } + + Widget _buildPayOptions() { + return ValueListenableBuilder( + valueListenable: activePay, + builder: (context, active, _) { + return Wrap( + spacing: 7.w, + runSpacing: 7.w, + children: [ + ...payList.asMap().entries.map( + (entry) { + return LiveRoomPayItem( + item: entry.value, + active: active ?? 0, + index: entry.key, + changeActive: changePayActive, + ); + }, + ), + ], + ); + }, + ); + } + + Widget _buildAgreementRow() { + return Padding( + padding: EdgeInsets.only(top: 10.w, bottom: 15.w), + child: Column( + children: [ + Container( + height: 1, + color: const Color.fromRGBO(219, 219, 219, 1), + ), + SizedBox(height: 15.w), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Image.asset( + Assets.imagesAliPay, + width: 17.w, + height: 17.w, + ), + SizedBox(width: 6.w), + Text( + "支付宝支付", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(51, 51, 51, 1), + ), + ), + ], + ), + ValueListenableBuilder( + valueListenable: payChecked, + builder: (context, checked, _) { + return GestureDetector( + onTap: () => payChecked.value = !payChecked.value, + child: Row( + children: [ + Container( + width: 14.w, + height: 14.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(2.w)), + color: checked + ? const Color.fromRGBO(239, 19, 46, 1) + : Colors.white, + border: Border.all( + width: 1, + color: checked + ? const Color.fromRGBO(239, 19, 46, 1) + : const Color.fromRGBO(188, 188, 188, 1), + ), + ), + child: Center( + child: Image.asset( + Assets.imagesCheck, + width: 6.w, + height: 4.w, + color: checked ? Colors.white : Colors.transparent, + ), + ), + ), + SizedBox(width: 6.w), + Text( + "我已阅读并同意《充值协议》", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(144, 144, 144, 1), + ), + ), + ], + ), + ); + }, + ), + ], + ), + ], + ), + ); + } + + Widget _buildSubmitButton() { + return Container( + width: double.infinity, + height: 44.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(44.w)), + gradient: const LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Color.fromRGBO(239, 19, 46, 1), + Color.fromRGBO(255, 183, 22, 1), + ], + ), + ), + child: Center( + child: Text( + "立即充值", + style: TextStyle( + fontSize: 13.w, + color: Colors.white, + fontWeight: FontWeight.w500, + ), + ), + ), + ); + } +} + diff --git a/lib/widget/live/live_room_action_bar.dart b/lib/widget/live/live_room_action_bar.dart new file mode 100644 index 0000000..a83ee8b --- /dev/null +++ b/lib/widget/live/live_room_action_bar.dart @@ -0,0 +1,121 @@ +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class LiveRoomActionBar extends StatelessWidget { + const LiveRoomActionBar({ + super.key, + required this.messageController, + required this.onMessageChanged, + required this.onGiftTap, + required this.onChargeTap, + }); + + final TextEditingController messageController; + final ValueChanged onMessageChanged; + final VoidCallback onGiftTap; + final VoidCallback onChargeTap; + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Container( + margin: EdgeInsets.only(left: 16.w), + child: InkWell( + onTap: onGiftTap, + child: Container( + width: 38.w, + height: 38.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(38.w)), + color: const Color.fromRGBO(0, 0, 0, .3), + ), + child: Center( + child: Image.asset( + Assets.imagesGiftIcon, + width: 28.w, + height: 28.w, + ), + ), + ), + ), + ), + SizedBox(width: 9.w), + Expanded( + child: Container( + height: 38.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(38.w)), + color: const Color.fromRGBO(0, 0, 0, .3), + ), + child: TextField( + controller: messageController, + keyboardType: TextInputType.number, + style: TextStyle( + fontSize: ScreenUtil().setWidth(14), + height: 1, + color: Colors.white, + ), + decoration: InputDecoration( + contentPadding: EdgeInsets.symmetric( + vertical: 0, + horizontal: 37.w, + ), + hintText: "聊点什么吧~", + hintStyle: TextStyle( + color: const Color.fromRGBO(144, 144, 144, 1), + ), + border: InputBorder.none, + ), + onChanged: onMessageChanged, + ), + ), + ), + SizedBox(width: 8.w), + Container( + width: 38.w, + height: 38.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(38.w)), + color: const Color.fromRGBO(0, 0, 0, .3), + ), + child: Center( + child: Image.asset( + Assets.imagesArrowR, + width: 16.w, + height: 16.w, + ), + ), + ), + SizedBox(width: 8.w), + InkWell( + onTap: onChargeTap, + child: Container( + width: 38.w, + height: 38.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(38.w)), + gradient: const LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Color.fromRGBO(255, 43, 110, 1), + Color.fromRGBO(255, 52, 26, 1), + ], + ), + ), + child: Center( + child: Image.asset( + Assets.imagesRoseWhite, + width: 14.w, + height: 25.w, + ), + ), + ), + ), + ], + ); + } +} + diff --git a/lib/widget/live/live_room_active_speaker.dart b/lib/widget/live/live_room_active_speaker.dart new file mode 100644 index 0000000..bf55b82 --- /dev/null +++ b/lib/widget/live/live_room_active_speaker.dart @@ -0,0 +1,54 @@ +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.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, + ), + ), + ), + 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, + ), + ), + ), + ), + ], + ), + ], + ); + } +} + diff --git a/lib/widget/live/live_room_anchor_showcase.dart b/lib/widget/live/live_room_anchor_showcase.dart new file mode 100644 index 0000000..8522a2c --- /dev/null +++ b/lib/widget/live/live_room_anchor_showcase.dart @@ -0,0 +1,195 @@ +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class LiveRoomAnchorShowcase extends StatelessWidget { + const LiveRoomAnchorShowcase({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Stack( + children: [ + Container( + width: 177.w, + height: 175.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(9.w)), + color: const Color.fromRGBO(47, 10, 94, 1), + ), + ), + Positioned( + top: 5.w, + left: 5.w, + child: Container( + width: 42.w, + height: 13.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(13.w)), + color: const Color.fromRGBO(142, 20, 186, 1), + ), + child: Center( + child: Text( + "主持人", + style: TextStyle( + fontSize: 9.w, + color: Colors.white, + ), + ), + ), + ), + ), + Positioned( + top: 5.w, + right: 5.w, + child: Container( + width: 20.w, + height: 20.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20.w)), + color: const Color.fromRGBO(0, 0, 0, .3), + ), + child: Center( + child: Image.asset( + Assets.imagesGiftIcon, + width: 19.w, + height: 19.w, + ), + ), + ), + ), + Positioned( + bottom: 5.w, + right: 5.w, + child: Container( + width: 47.w, + height: 20.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20.w)), + color: Colors.white, + ), + child: Center( + child: Text( + "加好友", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(117, 98, 249, 1), + ), + ), + ), + ), + ), + ], + ), + SizedBox(height: 5.w), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _buildSideAnchorCard( + isLeft: true, + micIcon: Assets.imagesMicClose, + ), + _buildSideAnchorCard( + isLeft: false, + micIcon: Assets.imagesMicOpen, + ), + ], + ), + ], + ); + } + + Widget _buildSideAnchorCard({ + required bool isLeft, + required String micIcon, + }) { + return Stack( + children: [ + Container( + width: 177.w, + height: 175.w, + decoration: BoxDecoration( + borderRadius: isLeft + ? BorderRadius.horizontal(left: Radius.circular(18.w)) + : BorderRadius.horizontal(right: Radius.circular(18.w)), + color: const Color.fromRGBO(47, 10, 94, 1), + ), + ), + Positioned( + top: 5.w, + right: 5.w, + child: Container( + width: 20.w, + height: 20.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20.w)), + color: const Color.fromRGBO(0, 0, 0, .3), + ), + child: Center( + child: Image.asset( + Assets.imagesGiftIcon, + width: 19.w, + height: 19.w, + ), + ), + ), + ), + Positioned( + bottom: 5.w, + right: 5.w, + child: Container( + width: 47.w, + height: 20.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(20.w)), + color: Colors.white, + ), + child: Center( + child: Text( + "加好友", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(117, 98, 249, 1), + ), + ), + ), + ), + ), + Positioned( + left: 5.w, + bottom: 5.w, + child: Row( + children: [ + 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, + ), + ), + ), + SizedBox(width: 5.w), + Text( + "飞翔的企鹅", + style: TextStyle( + fontSize: 11.w, + color: Colors.white, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ], + ); + } +} + diff --git a/lib/widget/live/live_room_chat_item.dart b/lib/widget/live/live_room_chat_item.dart new file mode 100644 index 0000000..e0378c6 --- /dev/null +++ b/lib/widget/live/live_room_chat_item.dart @@ -0,0 +1,44 @@ +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class LiveRoomChatItem extends StatelessWidget { + const LiveRoomChatItem({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + width: 260.w, + margin: EdgeInsets.only(bottom: 15.w), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.asset(Assets.imagesUserAvatar, width: 25.w, height: 25.w), + SizedBox(width: 10.w), + SizedBox( + width: 224.w, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: "沙发沙发:", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(155, 138, 246, 1), + ), + ), + TextSpan( + text: + "大家好啊!大家好啊!大家好啊!大家好啊!大家好啊!大家好啊!大家好啊!大家好啊!大家好啊!", + style: TextStyle(fontSize: 11.w, color: Colors.white), + ), + ], + ), + ), + ), + ], + ), + ); + } +} + diff --git a/lib/widget/live/live_room_gift_item.dart b/lib/widget/live/live_room_gift_item.dart new file mode 100644 index 0000000..a74be2e --- /dev/null +++ b/lib/widget/live/live_room_gift_item.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class LiveRoomGiftItem extends StatefulWidget { + final Map item; + final int active; + final int index; + final void Function(int) changeActive; + const LiveRoomGiftItem({ + super.key, + required this.item, + required this.active, + required this.index, + required this.changeActive, + }); + + @override + State createState() => _LiveRoomGiftItemState(); +} + +class _LiveRoomGiftItemState extends State { + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + widget.changeActive(widget.index); + }, + child: Container( + width: 83.w, + height: 94.w, + padding: EdgeInsets.only(top: 10.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(9.w)), + color: Color.fromRGBO( + 117, + 98, + 249, + widget.active == widget.index ? .2 : 0, + ), + border: Border.all( + width: 1, + color: Color.fromRGBO( + 117, + 98, + 249, + widget.active == widget.index ? 1 : 0, + ), + ), + ), + child: Column( + children: [ + Image.asset(widget.item["icon"], width: 41.w, height: 41.w), + SizedBox(height: 7.w), + Text( + widget.item["title"], + style: TextStyle(fontSize: 11.w, color: Colors.white), + ), + SizedBox(height: 1.w), + Text( + "${widget.item["price"]}支", + style: TextStyle( + fontSize: 7.w, + color: const Color.fromRGBO(144, 144, 144, 1), + ), + ), + ], + ), + ), + ); + } +} + diff --git a/lib/widget/live/live_room_notice_chat_panel.dart b/lib/widget/live/live_room_notice_chat_panel.dart new file mode 100644 index 0000000..0630e9e --- /dev/null +++ b/lib/widget/live/live_room_notice_chat_panel.dart @@ -0,0 +1,53 @@ +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:dating_touchme_app/widget/live/live_room_chat_item.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class LiveRoomNoticeChatPanel extends StatelessWidget { + const LiveRoomNoticeChatPanel({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + height: 230.w, + padding: EdgeInsets.only(left: 13.w, right: 9.w), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: SingleChildScrollView( + child: Column( + children: [ + Text( + "欢迎来到直播间!严禁未成年人直播或礼物消费。严禁违法违规、低俗色情、吸烟酗酒、人身伤害等直播内容。理性消费如主播在直播中以不当方式诱导消费,请谨慎辨别。切勿私下交易,以防人身财产损失,谨防网络诈骗。", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(155, 138, 246, 1), + ), + ), + SizedBox(height: 15.w), + const LiveRoomChatItem(), + const LiveRoomChatItem(), + const LiveRoomChatItem(), + const LiveRoomChatItem(), + const LiveRoomChatItem(), + const LiveRoomChatItem(), + const LiveRoomChatItem(), + const LiveRoomChatItem(), + const LiveRoomChatItem(), + ], + ), + ), + ), + SizedBox(width: 18.w), + Image.asset( + Assets.imagesAd, + width: 73.w, + fit: BoxFit.cover, + ), + ], + ), + ); + } +} + diff --git a/lib/widget/live/live_room_pay_item.dart b/lib/widget/live/live_room_pay_item.dart new file mode 100644 index 0000000..3e229e6 --- /dev/null +++ b/lib/widget/live/live_room_pay_item.dart @@ -0,0 +1,152 @@ +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class LiveRoomPayItem extends StatefulWidget { + final Map item; + final int active; + final int index; + final void Function(int) changeActive; + const LiveRoomPayItem({ + super.key, + required this.item, + required this.active, + required this.index, + required this.changeActive, + }); + + @override + State createState() => _LiveRoomPayItemState(); +} + +class _LiveRoomPayItemState extends State { + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () { + widget.changeActive(widget.index); + }, + child: Stack( + children: [ + Container( + width: 113.w, + height: 55.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(9.w)), + color: widget.active == widget.index + ? const Color.fromRGBO(239, 19, 46, .05) + : const Color.fromRGBO(247, 247, 247, 1), + border: widget.active == widget.index + ? Border.all( + width: 1, + color: const Color.fromRGBO(239, 19, 46, 1), + ) + : null, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + RichText( + text: TextSpan( + children: [ + TextSpan( + text: "${widget.item["num"]}", + style: TextStyle( + fontSize: 17.w, + color: const Color.fromRGBO(51, 51, 51, 1), + fontWeight: FontWeight.w700, + ), + ), + TextSpan( + text: "玫瑰", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(51, 51, 51, 1), + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + Text( + "${widget.item["price"]}元", + style: TextStyle( + fontSize: 11.w, + color: const Color.fromRGBO(144, 144, 144, 144), + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + if (widget.item["hasTag"]) + Positioned( + top: 0, + left: 0, + child: Container( + width: 53.w, + height: 11.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(9.w), + bottomRight: Radius.circular(9.w), + ), + color: widget.active == widget.index + ? null + : const Color.fromRGBO(238, 24, 50, .1), + gradient: widget.active == widget.index + ? LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: const [ + Color.fromRGBO(238, 24, 50, 1), + Color.fromRGBO(250, 101, 64, 1), + Color.fromRGBO(255, 131, 69, 1), + ], + stops: const [0.0, 0.7216, 1.0], + ) + : null, + ), + child: Center( + child: Text( + "送新人大礼包", + style: TextStyle( + fontSize: 6.w, + color: widget.active == widget.index + ? Colors.white + : const Color.fromRGBO(237, 23, 50, 1), + fontWeight: FontWeight.w500, + ), + ), + ), + ), + ), + if (widget.active == widget.index) + Positioned( + right: 0, + bottom: 0, + child: Container( + width: 17.w, + height: 13.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(9.w), + bottomRight: Radius.circular(9.w), + ), + color: const Color.fromRGBO(239, 19, 46, 1), + ), + child: Center( + child: Image.asset( + Assets.imagesCheck, + width: 6.w, + height: 4.w, + ), + ), + ), + ), + ], + ), + ); + } +} + diff --git a/lib/widget/live/live_room_seat_list.dart b/lib/widget/live/live_room_seat_list.dart new file mode 100644 index 0000000..77be33a --- /dev/null +++ b/lib/widget/live/live_room_seat_list.dart @@ -0,0 +1,128 @@ +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class LiveRoomSeatList extends StatelessWidget { + const LiveRoomSeatList({super.key}); + + @override + Widget build(BuildContext context) { + final seatLabelWidths = [ + 23.w, + 23.w, + 28.w, + 28.w, + 28.w, + 28.w, + 28.w, + 28.w, + ]; + + return Container( + width: 375.w, + height: 55.w, + padding: EdgeInsets.symmetric(horizontal: 6.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(9.w)), + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: const [ + Color.fromRGBO(46, 19, 79, 1), + Color.fromRGBO(61, 67, 130, 1), + Color.fromRGBO(64, 23, 115, 1), + Color.fromRGBO(26, 28, 86, 1), + ], + stops: const [0.0, 0.3153, 0.7209, 1.0], + ), + border: Border.all( + width: 1, + color: const Color.fromRGBO(117, 102, 255, 1), + ), + ), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: seatLabelWidths + .map( + (labelWidth) => Padding( + padding: EdgeInsets.symmetric(horizontal: 7.w), + child: _SeatItem(labelWidth: labelWidth), + ), + ) + .toList(), + ), + ), + ); + } +} + +class _SeatItem extends StatelessWidget { + const _SeatItem({required this.labelWidth}); + + final double labelWidth; + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Image.asset( + Assets.imagesSeat, + width: 35.w, + height: 35.w, + ), + Positioned( + bottom: 0, + left: 3.w, + child: Container( + width: labelWidth, + height: 12.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(4.w)), + color: const Color.fromRGBO(0, 0, 0, .65), + ), + child: Row( + children: [ + Expanded( + child: Center( + child: Text( + "1", + style: TextStyle( + fontSize: 8.w, + color: Colors.white, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + Container( + width: 12.w, + height: 12.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(12.w)), + gradient: const LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Color.fromRGBO(131, 89, 255, 1), + Color.fromRGBO(61, 138, 224, 1), + ], + ), + ), + child: Center( + child: Image.asset( + Assets.imagesMicClose, + width: 6.w, + height: 7.w, + ), + ), + ), + ], + ), + ), + ), + ], + ); + } +} + diff --git a/lib/widget/live/live_room_user_header.dart b/lib/widget/live/live_room_user_header.dart new file mode 100644 index 0000000..f149e02 --- /dev/null +++ b/lib/widget/live/live_room_user_header.dart @@ -0,0 +1,128 @@ +import 'package:dating_touchme_app/generated/assets.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +/// 直播间顶部用户信息与操作区域 +class LiveRoomUserHeader extends StatelessWidget { + const LiveRoomUserHeader({ + super.key, + required this.userName, + required this.popularityText, + this.avatarAsset = Assets.imagesUserAvatar, + this.fireIconAsset = Assets.imagesFireIcon, + this.closeIconAsset = Assets.imagesCloseArrow, + this.onFollowTap, + this.onCloseTap, + }); + + final String userName; + final String popularityText; + final String avatarAsset; + final String fireIconAsset; + final String closeIconAsset; + final VoidCallback? onFollowTap; + final VoidCallback? onCloseTap; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + height: 40.w, + padding: EdgeInsets.symmetric(horizontal: 3.w), + margin: EdgeInsets.only(left: 10.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(40.w)), + color: const Color.fromRGBO(0, 0, 0, .25), + ), + child: Row( + children: [ + Image.asset( + avatarAsset, + width: 34.w, + height: 34.w, + ), + SizedBox(width: 7.w), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + userName, + style: TextStyle( + fontSize: 13.w, + color: Colors.white, + ), + ), + SizedBox(height: 2.w), + Row( + children: [ + Image.asset( + fireIconAsset, + width: 10.w, + height: 12.w, + ), + SizedBox(width: 4.w), + Text( + popularityText, + style: TextStyle( + fontSize: 10.w, + color: Colors.white, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ], + ), + SizedBox(width: 15.w), + GestureDetector( + onTap: onFollowTap, + child: Container( + width: 47.w, + height: 27.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(27.w)), + color: const Color.fromRGBO(253, 43, 84, 1), + ), + child: Center( + child: Text( + '关注', + style: TextStyle( + fontSize: 13.w, + color: Colors.white, + fontWeight: FontWeight.w500, + height: 1, + ), + ), + ), + ), + ), + ], + ), + ), + GestureDetector( + onTap: onCloseTap, + child: Container( + width: 30.w, + height: 30.w, + margin: EdgeInsets.only(right: 15.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(30.w)), + color: const Color.fromRGBO(0, 0, 0, .3), + ), + child: Center( + child: Image.asset( + closeIconAsset, + width: 14.w, + height: 14.w, + ), + ), + ), + ), + ], + ); + } +} +