Flutter:实现带可折叠bottom的StatefulWidget版AppBar遇问题
解决Flutter可折叠Bottom的StatefulWidget版AppBar高度异常问题
问题根源
你封装的MyAppBar中,preferredSize是固定值,而控制bottom显示的expand状态仅存在于State类中。由于StatefulWidget的实例不可变,setState只会触发State的重建,无法更新Widget类的preferredSize,导致AppBar整体高度不随bottom的显隐变化,要么顶部栏上移、要么折叠后留空白。
解决方案
方案一:基于原生AppBar封装,让Widget响应状态变化
将控制状态的变量移到MyAppBar类中,用ValueNotifier监听变化,确保preferredSize能动态计算:
import 'package:flutter/material.dart'; class MyAppBar extends StatefulWidget implements PreferredSizeWidget { MyAppBar({Key? key}) : super(key: key); final ValueNotifier<bool> _expandNotifier = ValueNotifier(false); bool get expand => _expandNotifier.value; set expand(bool value) => _expandNotifier.value = value; @override Size get preferredSize => Size.fromHeight( kToolbarHeight + (expand ? kToolbarHeight : 0), ); @override State<MyAppBar> createState() => MyAppBarState(); } class MyAppBarState extends State<MyAppBar> { @override void initState() { super.initState(); widget._expandNotifier.addListener(() => setState(() {})); } @override void dispose() { widget._expandNotifier.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return AppBar( title: const Text("可折叠底部栏"), leading: IconButton( icon: Icon(widget.expand ? Icons.expand_less : Icons.expand_more), onPressed: () => widget.expand = !widget.expand, ), bottom: widget.expand ? PreferredSize( preferredSize: const Size.fromHeight(kToolbarHeight), child: Container( height: kToolbarHeight, color: Colors.blue[200], child: const Center(child: Text("底部栏内容")), ), ) : null, ); } }
方案二:自定义AppBar结构,直接控制高度
不依赖原生AppBar,自己构建顶部栏和可折叠底部栏,直接通过State控制整体高度:
import 'package:flutter/material.dart'; class MyAppBar extends StatefulWidget implements PreferredSizeWidget { MyAppBar({Key? key}) : super(key: key); @override Size get preferredSize => _MyAppBarState.preferredSize; @override State<MyAppBar> createState() => _MyAppBarState(); } class _MyAppBarState extends State<MyAppBar> { static Size preferredSize = Size.fromHeight(kToolbarHeight); bool expand = false; void _toggleExpand() { setState(() { expand = !expand; preferredSize = Size.fromHeight( kToolbarHeight + (expand ? kToolbarHeight : 0), ); }); } @override Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, children: [ Container( height: kToolbarHeight, color: Theme.of(context).primaryColor, child: Row( children: [ IconButton( icon: Icon(expand ? Icons.expand_less : Icons.expand_more), onPressed: _toggleExpand, color: Colors.white, ), const Text( "可折叠标题栏", style: TextStyle(color: Colors.white, fontSize: 18), ), ], ), ), if (expand) Container( height: kToolbarHeight, color: Theme.of(context).primaryColorLight, child: const Center(child: Text("底部栏内容")), ), ], ); } }
核心思路
确保PreferredSizeWidget的preferredSize能实时响应bottom的显隐状态:要么让Widget类能获取到控制状态,要么直接自定义布局来把控整体高度,避免原生AppBar的高度限制导致的布局异常。
内容的提问来源于stack exchange,提问作者stackunderflow
相关产品推荐
相关产品推荐

