Flutter中实现PreferredSizeWidget的组件如何结合Obx响应更新preferredSize
解决方案
方案1:优先使用Flutter自带PreferredSize组件(最简实现)
不需要手动实现PreferredSizeWidget接口,直接将动态逻辑完全包裹在Obx内,每次状态变化时返回对应高度的PreferredSize组件,AppBar会自动读取最新的高度参数:
class BottomOfAppBar extends StatelessWidget { BottomOfAppBar({Key? key, required this.tabs}) : super(key: key); final List<Widget> tabs; final tabbarenable2 = Get.find<RxBool>(tag: 'tabbarenable'); @override Widget build(BuildContext context) { return Obx(() => PreferredSize( preferredSize: tabbarenable2.value ? const Size.fromHeight(28.0) : const Size.fromHeight(0.0), child: ColoredBox( color: Colors.white, child: Column( children: [ if (tabbarenable2.value) TabBar( labelColor: Colors.purple[100], indicatorColor: Colors.purple, isScrollable: true, labelPadding: const EdgeInsets.only(left: 8.0), tabs: tabs, ) // 隐藏时用空占位组件代替Text即可 else const SizedBox.shrink(), ], ), ), )); } }
方案2:自定义PreferredSizeWidget配合状态监听
如果必须保留自定义PreferredSizeWidget的实现,可将组件改为Stateful,监听Rx变量变化主动触发组件刷新,让AppBar重新读取preferredSize:
class BottomOfAppBar extends StatefulWidget implements PreferredSizeWidget { const BottomOfAppBar({Key? key, required this.tabs}) : super(key: key); final List<Widget> tabs; @override State<BottomOfAppBar> createState() => _BottomOfAppBarState(); @override Size get preferredSize => Get.find<RxBool>(tag: 'tabbarenable').value ? const Size.fromHeight(28.0) : const Size.fromHeight(0.0); } class _BottomOfAppBarState extends State<BottomOfAppBar> { final tabbarenable2 = Get.find<RxBool>(tag: 'tabbarenable'); late Worker _statusListener; @override void initState() { super.initState(); // 监听状态变化,触发组件刷新 _statusListener = ever(tabbarenable2, (_) => setState(() {})); } @override void dispose() { // 销毁监听避免内存泄漏 _statusListener.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Obx(() => Container( child: ColoredBox( color: Colors.white, child: Column( children: [ tabbarenable2.value ? TabBar( labelColor: Colors.purple[100], indicatorColor: Colors.purple, isScrollable: true, labelPadding: const EdgeInsets.only(left: 8.0), tabs: widget.tabs) : const SizedBox.shrink() ], ), ), )); } }
原问题根因
AppBar仅在自身需要重新布局时才会读取bottom属性的preferredSize值,原写法中只有build返回的子树被Obx包裹,状态变化时仅刷新子控件,不会触发AppBar重新读取高度参数,因此高度不会跟随状态变化。
内容的提问来源于stack exchange,提问作者gegentierversuche
相关产品推荐
相关产品推荐

