import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:yumi/app/constants/sc_global_config.dart'; import 'package:yumi/shared/data_sources/sources/local/user_manager.dart'; import 'package:yumi/modules/index/main_route.dart'; import 'package:yumi/services/auth/user_profile_manager.dart'; import 'package:provider/provider.dart'; import 'package:yumi/app/routes/sc_fluro_navigator.dart'; import 'package:yumi/ui_kit/widgets/countdown_timer.dart'; import 'package:yumi/ui_kit/widgets/sc_home_shell_background.dart'; ///Home页面 class SCIndexHomePage extends StatefulWidget { const SCIndexHomePage({super.key}); @override State createState() => _SCIndexHomePageState(); } class _SCIndexHomePageState extends State with TickerProviderStateMixin { TabController? _tabController; final List _pages = []; final List _tabs = []; Locale? _lastLocale; @override void didChangeDependencies() { super.didChangeDependencies(); final locale = Localizations.localeOf(context); if (_lastLocale == locale && _tabController != null && _pages.isNotEmpty) { return; } _lastLocale = locale; _rebuildTabs(); } void _rebuildTabs() { final strategy = SCGlobalConfig.businessLogicStrategy; final nextPages = strategy.getHomeTabPages(context); final nextTabs = strategy.getHomeTabLabels(context); if (nextPages.isEmpty || nextTabs.length != nextPages.length) { return; } final desiredIndex = _tabController?.index ?? strategy.getHomeInitialTabIndex(); final initialIndex = desiredIndex.clamp(0, nextPages.length - 1); _tabController?.dispose(); _pages ..clear() ..addAll(nextPages); _tabs ..clear() ..addAll(nextTabs); _tabController = TabController( length: _pages.length, vsync: this, initialIndex: initialIndex, ); } @override void dispose() { _tabController?.dispose(); super.dispose(); } Widget _buildStyledTab(Widget tab, int index) { final controller = _tabController!; if (tab is! Tab || tab.text == null) return tab; return Tab( height: tab.height, child: AnimatedBuilder( animation: controller.animation!, builder: (context, child) { if (controller.index != index) return child!; return SCHomeShellGradientText( tab.text!, style: DefaultTextStyle.of(context).style, ); }, child: Text(tab.text!), ), ); } @override Widget build(BuildContext context) { if (_tabController == null || _pages.isEmpty || _tabs.isEmpty) { return Center( child: Container( decoration: BoxDecoration( color: Colors.black26, borderRadius: BorderRadius.circular(8), ), width: 55.w, height: 55.w, child: const CupertinoActivityIndicator(), ), ); } return Stack( children: [ const Positioned.fill(child: SCHomeShellBackground()), Scaffold( resizeToAvoidBottomInset: false, backgroundColor: Colors.transparent, body: Column( children: [ // 自定义顶部栏(包含状态栏和 TabBar) SafeArea( bottom: false, child: SizedBox( height: 44.w, child: Row( children: [ // TabBar 直接放在这里 Expanded( child: TabBar( tabAlignment: TabAlignment.start, isScrollable: true, labelPadding: EdgeInsets.symmetric(horizontal: 10.w), splashFactory: NoSplash.splashFactory, overlayColor: WidgetStateProperty.all( Colors.transparent, ), indicator: const BoxDecoration(), labelStyle: TextStyle( fontWeight: FontWeight.w900, fontStyle: FontStyle.italic, fontSize: 28.sp, color: scHomeShellGoldColor, shadows: const [ Shadow( color: Color(0xB3000000), offset: Offset(0, 1), blurRadius: 1, ), ], ), unselectedLabelStyle: TextStyle( fontWeight: FontWeight.w600, fontSize: 16.sp, color: Colors.white, ), indicatorColor: Colors.transparent, dividerColor: Colors.transparent, controller: _tabController, tabs: List.generate( _tabs.length, (index) => _buildStyledTab(_tabs[index], index), ), ), ), Container( padding: EdgeInsetsDirectional.only(end: 10.w), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ IconButton( icon: Image.asset( "sc_images/index/sc_icon_serach.png", width: 25.w, height: 25.w, ), onPressed: () => SCNavigatorUtils.push( context, SCMainRoute.mainSearch, ), ), ], ), ), ], ), ), ), // TabBarView 直接作为剩余空间 Expanded( child: TabBarView(controller: _tabController, children: _pages), ), ], ), ), Consumer( builder: (context, ref, child) { if (SCGlobalConfig.isReview) return Container(); final strategy = SCGlobalConfig.businessLogicStrategy; if (strategy.shouldShowFirstRechargePrompt()) { final position = strategy.getFirstRechargePosition(); return PositionedDirectional( top: position['top'], bottom: position['bottom'], start: position['start'], end: position['end'], child: GestureDetector( child: Column( children: [ Image.asset( "sc_images/index/sc_icon_first_recharge_tag.webp", height: 70.w, ), Transform.translate( offset: Offset(0, -10), child: Container( height: 23.w, width: 100.w, alignment: AlignmentDirectional.center, decoration: BoxDecoration( image: DecorationImage( image: AssetImage( "sc_images/index/sc_icon_first_recharge_btn.png", ), fit: BoxFit.fill, ), ), child: CountdownTimer( expiryDate: DateTime.fromMillisecondsSinceEpoch( AccountStorage() .getCurrentUser() ?.userProfile ?.firstRechargeEndTime ?? 0, ), color: Colors.white, ), ), ), ], ), onTap: () { strategy.onFirstRechargeTap(context); }, ), ); } return Container(); }, ), ], ); } }