点击右边的按钮切换到“个人中心”页
/rootpage @override void didChangeDependencies() { print('root didChangeDependencies'); super.didChangeDependencies(); var widgetsBinding = WidgetsBinding.instance; widgetsBinding.addPostFrameCallback((callback) { print('addPostFrameCallback'); PNavigationBar.show(context, _tabController); }); }我将这个放入到了didChangeDependencies内,主要是想通过混入TickerProviderStateMixin能够在路由回来时重新触发didChangeDependencies,不过理想很丰满。最后在实验的过程中反倒没有触发,没有找到原因,希望有感兴趣的大佬可以指点一下。
@override Widget build(BuildContext context) { return Scaffold( body: TabBarView( controller: _tabController, children: [ HomePage(), UserPage(), ], ), ); }这里需要一个TabController,相信比较熟悉的朋友们也知道,需要混入TickerProviderStateMixin,才可以声明
当然整个TabBar的渲染逻辑其实是有问题的,想要更深入地改TabBar的排列方式,必须需要自己手写一个TabBar。默认的排列方式就是放到Expanded内的。
import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:picturebook/pages/test/test_page.dart'; import '../color_utils.dart'; // 堆代码 duidaima.com class PNavigationBar { static OverlayEntry? overlayEntry; static show(BuildContext context, TabController tabController) { var overlayState = Overlay.of(context); overlayEntry = OverlayEntry( maintainState: true, builder: (BuildContext context) { final size = MediaQuery.of(context).size; final height = size.height; final width = size.width; final boxWidth = width * 0.46; final boxHeight = 60.h; final iconHeight = 45.h; return Positioned( bottom: height * 0.06, left: (width - boxWidth) / 2, right: (width - boxWidth) / 2, child: Stack( children: [ Container( decoration: BoxDecoration( color: ColorUtils.orange, borderRadius: BorderRadius.circular(boxHeight / 2), ), width: boxWidth, height: boxHeight, child: TabBar( controller: tabController, indicatorColor: Colors.transparent, padding: EdgeInsets.zero, onTap: (index) { tabController.animateTo(index); overlayEntry?.markNeedsBuild(); }, tabs: [ Padding( padding: EdgeInsets.only(right: iconHeight / 3), child: Container( width: iconHeight, height: iconHeight, decoration: BoxDecoration( color: Colors.white30, borderRadius: BorderRadius.circular(iconHeight / 2), ), child: Center( child: Image.asset( tabController.index == 0 ? 'assets/home_1.png' : 'assets/home_0.png', width: iconHeight * 0.5, )), ), ), Padding( padding: EdgeInsets.only(left: iconHeight / 3), child: Container( width: iconHeight, height: iconHeight, decoration: BoxDecoration( color: Colors.white30, borderRadius: BorderRadius.circular(iconHeight / 2), ), child: Center( child: Image.asset( tabController.index == 1 ? 'assets/user_1.png' : 'assets/user_0.png', width: iconHeight * 0.5, )), ), ), ], )), Align( alignment: Alignment.center, child: Padding( padding: EdgeInsets.only(top: (boxHeight - iconHeight) / 2), child: InkWell( onTap: () { print('push'); Navigator.push( context, MaterialPageRoute(builder: (context) => TestPage()), ); }, child: Container( width: iconHeight, height: iconHeight, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(iconHeight / 2), ), child: Center( child: Image.asset( 'assets/add.png', width: iconHeight * 0.5, )), ), ), ), ), ], ), ); }, ); overlayState.insert(overlayEntry!); } static remove() { if (overlayEntry != null) { overlayEntry!.remove(); } } static refresh(){ overlayEntry?.markNeedsBuild(); } }下面是使用的实例,非常优美简洁:
import 'package:flutter/material.dart'; import 'package:lifecycle_lite/lifecycle_mixin.dart'; import 'package:picturebook/pages/home_page.dart'; import 'package:picturebook/pages/user_page.dart'; import 'package:picturebook/utils/navigation/navigation_util.dart'; class RootPage extends StatefulWidget { const RootPage({super.key}); @override State<RootPage> createState() => _RootPageState(); } class _RootPageState extends State<RootPage> with TickerProviderStateMixin, LifecycleStatefulMixin { late TabController _tabController; @override void initState() { super.initState(); _tabController = TabController(length: 2, vsync: this)..addListener(() { PNavigationBar.refresh(); }); } @override void didChangeDependencies() { super.didChangeDependencies(); var widgetsBinding = WidgetsBinding.instance; widgetsBinding.addPostFrameCallback((callback) { PNavigationBar.show(context, _tabController); }); } @override Widget build(BuildContext context) { return Scaffold( body: TabBarView( controller: _tabController, children: [ HomePage(), UserPage(), ], ), ); } @override void whenHide() { PNavigationBar.remove(); } @override void whenShow() { PNavigationBar.show(context, _tabController); } }