import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:hgdj/assets_tool/images.dart'; import 'package:hgdj/hj_page/home/provider/home_update_marker_provider.dart'; import 'package:hgdj/hj_utils/const.dart'; import 'package:hgdj/hj_utils/screen.dart'; import 'package:hgdj/tools_base/indicator/custom_tab_indicator.dart'; import 'package:hgdj/tools_base/loading/loading_center_widget.dart'; import 'package:hgdj/tools_base/widget/keep_alive_widget.dart'; import 'package:provider/provider.dart'; import '../cartoon/cartoon_sub_detail_page.dart'; import '../main_page/provider/bottom_bar_provider.dart'; import 'activity_float/home_float_widget.dart'; import 'home_drawer.dart'; import 'home_main_logic.dart'; import 'home_sub_module/home_tab_section_page.dart'; import 'home_sub_module/home_tab_sort_page.dart'; import 'search_page/widget/common_search_widget.dart'; class HomeMainPage extends StatelessWidget { const HomeMainPage({super.key}); @override Widget build(BuildContext context) { return Material( color: const Color(0xff050f17), child: GetBuilder( init: HomeMainLogic(), tag: "HomeMainLogic", builder: (logic) { return Stack( fit: StackFit.expand, children: [ Scaffold( key: logic.scaffoldKey, endDrawer: HSHomeDrawer(homeLogic: logic), body: _body(logic), ), //右下角活动浮窗 const Positioned(right: 12, bottom: 40, child: HomeFloatWidget()), ], ); }, ), ); } Widget _body(HomeMainLogic logic) { if (logic.isLoading) return const LoadingCenterWidget(); return Column( children: [ //顶部搜索栏(状态栏 + 导航栏高度) Container( color: Colors.black, padding: EdgeInsets.only(top: screen.paddingTop), height: kToolbarHeight + screen.paddingTop, child: CommonSearchBarView(logic: logic), ), //排序变化时 tabViewKey 变,整个 TabView 连 TabController 一起重建 Expanded( child: HomeTabView(key: ValueKey(logic.tabViewKey), logic: logic)), ], ); } } class HomeTabView extends StatefulWidget { final HomeMainLogic logic; final bool isDarkStyle; const HomeTabView({ super.key, required this.logic, this.isDarkStyle = false, }); @override State createState() => _HomeTabViewState(); } class _HomeTabViewState extends State with SingleTickerProviderStateMixin { HomeMainLogic get logic => widget.logic; bool get isDarkStyle => widget.isDarkStyle; late final TabController tabCtr; @override void initState() { super.initState(); final count = logic.tabs.length; tabCtr = TabController( // 防止 tab 数量不足时 initialIndex 越界导致断言崩溃 initialIndex: count > 0 ? logic.selectedTabIndex.clamp(0, count - 1) : 0, length: count, vsync: this, ); tabCtr.addListener(_onTabChange); logic.tabCtr = tabCtr; } @override void dispose() { // controller 在本 State vsync 创建,归本 State 释放(排序换 key 会重建 State) tabCtr.removeListener(_onTabChange); tabCtr.dispose(); // 换 key 重建时新 State 可能已把自己的 ctr 写进 logic,只清掉自己那一份 if (identical(logic.tabCtr, tabCtr)) logic.tabCtr = null; super.dispose(); } void _onTabChange() { if (tabCtr.indexIsChanging) return; if (isDarkStyle) { DarkwebBottomProvider().setScrollController(tabCtr.index); return; } HomeBottomProvider().setScrollController(tabCtr.index); final tabs = logic.tabs; if (tabCtr.index < tabs.length && tabs[tabCtr.index].id == '-110') { // 进入「最新」:清 Tab 红点;默认排序即「今日最新」,一并视为已查看 HomeUpdateMarkerProvider().markHomeLatestViewed(); HomeUpdateMarkerProvider().markTodayLatestViewed(); } } @override Widget build(BuildContext context) { return Column( children: [ Container( height: 48.h, color: Colors.black, child: _tabBar(), ), Expanded( child: Stack( fit: StackFit.expand, children: [ if (isDarkStyle) Image.asset("aw_bg.webp".homePath), TabBarView( controller: tabCtr, children: [ for (int i = 0; i < logic.tabs.length; i++) _tabPage(i) ], ), ], ), ), ], ); } Widget _tabBar() { return Consumer( builder: (_, marker, __) { return TabBar( tabAlignment: TabAlignment.start, tabs: logic.tabs.map((e) { //「最新」有更新时右上角挂红点 final showDot = !isDarkStyle && e.id == '-110' && marker.showHomeLatestDot; return Container( padding: EdgeInsets.symmetric(horizontal: 14.w), alignment: Alignment.center, child: Stack( clipBehavior: Clip.none, children: [ Text(e.moduleName ?? ''), if (showDot) Positioned( right: -8, top: -2, child: HomeUpdateMarkerProvider.buildRedDot(), ), ], ), ); }).toList(), isScrollable: true, padding: const EdgeInsets.only(bottom: 2), labelPadding: EdgeInsets.zero, unselectedLabelStyle: const TextStyle(fontSize: 14), unselectedLabelColor: const Color(0x73FFFFFF), labelStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500), labelColor: isDarkStyle ? const Color(0xff810906) : const Color(0xE5FFFFFF), indicator: CustomIndicator( height: 2, width: 16.w, color: const Color(0xfff68804), offsetY: 4, ), controller: tabCtr, ); }, ); } /// 按 module type/showType/isACG 分发到对应子页,统一 keepAlive Widget _tabPage(int index) { final module = logic.tabs[index]; if (module.type == 1 || module.type == 3) { //showType==2 走分区聚合页,其余走排序列表页 return module.showType == 2 ? HomeTabSectionPage(index, module, isDarkStyle: isDarkStyle) .keepAlive : HomeTabSortPage(index, module, isDarkStyle: isDarkStyle).keepAlive; } if (module.isACG) { return CartoonSubDetailPage(tagData: module, type: MediaStyle.Cartoon) .keepAlive; } return HomeTabSortPage(index, module, isDarkStyle: isDarkStyle).keepAlive; } }