288 lines
8.9 KiB
Dart
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]),
|
|
),
|
|
);
|
|
}
|
|
}
|