Flutter中AppBar尺寸变化时如何动态调整标题与actions内组件宽度
解决方案
你之前的方案未生效是因为AppBar默认自带leading占位、title边距、actions专属布局约束,无法直接通过子组件的弹性属性适配比例,我们可以通过自定义AppBar的title布局实现需求,完整修改代码如下:
完整可运行代码
/// Flutter code sample for AppBar import 'package:flutter/material.dart'; void main() => runApp(const AlbertsApp()); /// 主应用组件 class AlbertsApp extends StatelessWidget { const AlbertsApp({Key? key}) : super(key: key); static const String _title = 'Flutter Code Sample'; @override Widget build(BuildContext context) { return const MaterialApp( title: _title, home: MyStatelessWidget(), ); } } /// 主应用实例化的无状态组件 class MyStatelessWidget extends StatelessWidget { const MyStatelessWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( // 关闭默认leading相关占位,保证可用宽度等于AppBar总宽度 automaticallyImplyLeading: false, leadingWidth: 0, titleSpacing: 0, // 自定义title的Row布局控制全局比例 title: Row( children: [ // 标题占7份,对应总宽度70% const Expanded( flex: 7, child: Padding( padding: EdgeInsets.symmetric(horizontal: 16), child: Text( 'Alberts trial AppBar', overflow: TextOverflow.ellipsis, ), ), ), // 每个按钮占1份,3个按钮共占3份,对应总宽度30% Expanded( flex: 1, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.red, padding: EdgeInsets.zero, shape: const RoundedRectangleBorder(side: BorderSide.none), ), onPressed: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('This is a TonysChoocolonely'))); }, child: const Text('Hi'), ), ), Expanded( flex: 1, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.green, padding: EdgeInsets.zero, shape: const RoundedRectangleBorder(side: BorderSide.none), ), onPressed: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('This is a KitKat'))); }, child: const Text('Bye'), ), ), Expanded( flex: 1, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.yellow, padding: EdgeInsets.zero, shape: const RoundedRectangleBorder(side: BorderSide.none), ), onPressed: () { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('This is a PeanutButter'))); }, child: const Text('Third'), ), ), ], ), ), body: const Center( child: Text( 'This Is The Home Page Itself', style: TextStyle(fontSize: 24), ), ), ); } }
关键修改说明
- 关闭AppBar默认的leading相关配置:
automaticallyImplyLeading: false去掉默认返回按钮,leadingWidth: 0取消leading占位宽度,titleSpacing: 0去掉title左侧默认边距,确保布局可用宽度和AppBar总宽度完全一致 - 用Row作为AppBar的title属性的根组件,内部通过Expanded的flex属性分配宽度比例:
- 标题部分外层套Expanded,设置
flex:7,占总宽度的70%,可自行调整内边距适配视觉效果 - 每个按钮外层套Expanded,
flex设为1,3个按钮总flex为3,占总宽度的30%;如果实际场景只有1个action按钮,直接将按钮的flex设为3即可,刚好满足标题70%、按钮30%的需求
- 标题部分外层套Expanded,设置
- 按钮样式配置取消默认padding和边框,避免额外空间占用,你可以根据视觉需求自行调整
- 该实现完全跟随AppBar宽度动态适配,桌面端拖拽窗口、移动端横竖屏切换时都会保持比例不变
内容的提问来源于stack exchange,提问作者Albert Samvelyan
相关产品推荐
相关产品推荐

