Files
2026-09-15 15:44:13 +07:00

288 lines
8.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hgdj/assets_tool/images.dart';
import 'package:hgdj/hj_page/live/live_item_widget.dart';
import 'package:hgdj/hj_utils/screen.dart';
import 'package:hgdj/tools_base/banner/ads_grid_view_widget.dart';
import 'package:hgdj/tools_base/loading/loading_center_widget.dart';
import 'package:hgdj/tools_base/refresh/pull_refresh.dart';
import 'package:hgdj/tools_base/widget/card_swiper/src/swiper.dart';
import 'live_model.dart';
import 'live_sub_logic.dart';
//直播子列表页面
class LiveSubPage extends StatefulWidget {
final LiveModule? tagData;
const LiveSubPage({super.key, this.tagData});
@override
State<LiveSubPage> createState() => _LiveSubPageState();
}
class _LiveSubPageState extends State<LiveSubPage> {
String get _tag => widget.tagData?.id ?? '';
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('live_main_bg.webp'.livePath), fit: BoxFit.fill),
),
child: GetBuilder<LiveSubLogic>(
init: LiveSubLogic(tagData: widget.tagData),
tag: _tag,
builder: (logic) => pullYsRefresh(
enablePullUp: !logic.isRecom,
onInit: (c) => logic.controller = c,
onRefresh: (c) => logic.loadData(),
onLoading: (c) => logic.loadMoreData(),
child: _buildContent(logic),
),
),
);
}
Widget _buildContent(LiveSubLogic logic) {
//列表样式
if (!logic.isRecom) {
return CustomScrollView(
slivers: [_buildAdBanner(), _buildAnchorGrid(logic)]);
}
//推荐样式
if (logic.liveMainModel?.recom == null) return const LoadingCenterWidget();
if (logic.liveMainModel?.recom?.isEmpty == true) {
return CErrorWidget(retryOnTap: () => logic.loadData());
}
return CustomScrollView(slivers: _buildRecomItems(logic));
}
//广告 banner
Widget _buildAdBanner() {
return SliverToBoxAdapter(
child: AdsGridViewWidget(
35,
accordingAdsType: true,
padding: const EdgeInsets.fromLTRB(16, 15, 16, 15),
),
);
}
//国家/标签主播列表
Widget _buildAnchorGrid(LiveSubLogic logic) {
if (logic.loading) {
return const SliverToBoxAdapter(
child: SizedBox(height: 200, child: LoadingCenterWidget()));
}
if (logic.liveList.isEmpty) {
return SliverToBoxAdapter(
child: CErrorWidget(retryOnTap: () => logic.loadData()));
}
return SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 16),
sliver: SliverGrid(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 12,
crossAxisSpacing: 7,
childAspectRatio: 168 / 105,
),
delegate: SliverChildBuilderDelegate(
(_, index) =>
LiveItemWidget(showType: 5, anchor: logic.liveList[index]),
childCount: logic.liveList.length,
),
),
);
}
//推荐页各区块(首块额外叠充值入口)
List<Widget> _buildRecomItems(LiveSubLogic logic) {
final recomList = logic.liveMainModel?.recom ?? [];
return List.generate(recomList.length, (i) {
Widget section = _buildRecomSection(recomList[i]);
if (i == 0) section = _wrapFirstSection(logic, section);
return SliverToBoxAdapter(child: section);
});
}
//按 recoShowType 分发区块样式
Widget _buildRecomSection(LiveRecom recom) {
switch (recom.recoShowType) {
case 'nine_grid':
return _buildGridSection(recom,
bg: 'live_section_bg_1.webp',
title: 'nine_grid_bg.webp',
titleHeight: 45,
crossAxisCount: 3,
mainSpacing: 12,
crossSpacing: 5,
aspectRatio: 1,
showType: 0);
case 'six_round':
return _buildGridSection(recom,
bg: 'live_section_bg_2.webp',
title: 'six_round_bg.webp',
titleHeight: 45,
crossAxisCount: 2,
mainSpacing: 0,
crossSpacing: 6,
aspectRatio: 168 / 85,
showType: 1,
bottomSpace: 10);
case 'four_grid':
return _buildGridSection(recom,
bg: 'live_section_bg_3.webp',
title: 'four_grid_bg.webp',
titleHeight: 45,
crossAxisCount: 2,
mainSpacing: 12,
crossSpacing: 7,
aspectRatio: 1,
showType: 2,
bottomSpace: 18);
case 'six_grid':
return _buildGridSection(recom,
bg: 'live_section_bg_4.webp',
title: 'six_grid_bg.webp',
titleHeight: 36,
crossAxisCount: 3,
mainSpacing: 12,
crossSpacing: 5,
aspectRatio: 1,
showType: 3);
case 'horizontal_slide':
return _buildHorizontalSlide(recom);
case 'list':
return _buildRecomList(recom.anchors);
default:
return const SizedBox.shrink();
}
}
//首个区块叠加充值入口
Widget _wrapFirstSection(LiveSubLogic logic, Widget section) {
return Stack(
alignment: Alignment.topCenter,
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [178.sizeBoxH, section, 10.sizeBoxH]),
Positioned(
top: 20,
child: GestureDetector(
onTap: () => logic.onChargeAction(),
child: Image.asset('live_charge.webp'.livePath, height: 148),
),
),
],
);
}
//宫格类区块(九宫格/六圆形/四宫格/六宫格 共用)
Widget _buildGridSection(
LiveRecom? recom, {
required String bg,
required String title,
required double titleHeight,
required int crossAxisCount,
required double mainSpacing,
required double crossSpacing,
required double aspectRatio,
required int showType,
double bottomSpace = 0,
}) {
final anchors = recom?.anchors;
return Container(
decoration: BoxDecoration(
image:
DecorationImage(image: AssetImage(bg.livePath), fit: BoxFit.fill),
),
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
padding: const EdgeInsets.only(left: 12, right: 12, top: 4, bottom: 34),
child: Column(
children: [
18.sizeBoxH,
Image.asset(title.livePath, height: titleHeight),
18.sizeBoxH,
GridView.builder(
padding: EdgeInsets.zero,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
mainAxisSpacing: mainSpacing,
crossAxisSpacing: crossSpacing,
childAspectRatio: aspectRatio,
),
itemCount: anchors?.length ?? 0,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
//index 仅 showType==2 用于渲染前三角标,其余样式忽略
itemBuilder: (_, index) => LiveItemWidget(
showType: showType, anchor: anchors?[index], index: index),
),
if (bottomSpace > 0) bottomSpace.sizeBoxH,
],
),
);
}
//横向滑动
Widget _buildHorizontalSlide(LiveRecom? recom) {
final anchors = recom?.anchors;
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
const Color(0xffFF8E8E).withValues(alpha: 0),
const Color(0xffFF8E8E).withValues(alpha: .2),
const Color(0xffFF8E8E).withValues(alpha: 0),
],
),
),
child: Column(
children: [
18.sizeBoxH,
Container(
height: 175,
alignment: Alignment.bottomRight,
child: Swiper(
autoplay: true,
autoplayDelay: 5000,
viewportFraction: 0.8,
scale: 0.93,
itemCount: anchors?.length ?? 0,
itemBuilder: (c, index) =>
LiveItemWidget(showType: 4, anchor: anchors?[index]),
),
),
],
),
);
}
//推荐无限下滑列表
Widget _buildRecomList(List<LiveAnchor>? anchors) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 28),
child: GridView.builder(
padding: EdgeInsets.zero,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 12,
crossAxisSpacing: 5,
childAspectRatio: 168 / 105,
),
itemCount: anchors?.length ?? 0,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (_, index) =>
LiveItemWidget(showType: 5, anchor: anchors?[index]),
),
);
}
}