如何在Flutter中使用PreferredSize实现响应式高度的AppBar?
如何用PreferredSize实现响应式高度的AppBar
核心实现思路
要让AppBar高度在不同设备上自适应,关键是让PreferredSize的高度基于设备屏幕尺寸动态计算,而非固定数值。以下两种方式可实现需求:
方法1:基于MediaQuery动态计算
直接利用MediaQuery获取屏幕尺寸的比例值设置高度,确保在不同设备上保持一致的视觉占比:
class ResponsiveAppBar extends StatelessWidget implements PreferredSizeWidget { @override Size get preferredSize => Size.fromHeight(MediaQuery.of(context).size.height * 0.2); // 占屏幕高度20% @override Widget build(BuildContext context) { return Container( width: double.infinity, height: preferredSize.height, child: Stack( clipBehavior: Clip.none, children: [ Image.asset('assets/topBackground.png', fit: BoxFit.cover, height: double.infinity), Positioned( left: MediaQuery.of(context).size.width * 0.08, // 左间距占屏幕宽度8% top: MediaQuery.of(context).size.height * 0.025, child: SizedBox( width: MediaQuery.of(context).size.width * 0.84, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Icon(Icons.menu, color: Colors.white), CircleAvatar(child: Image.asset("assets/Emmanuel_Jerry.png")), ], ), ), ), Positioned( top: MediaQuery.of(context).size.height * 0.06, left: MediaQuery.of(context).size.width * 0.1, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: MediaQuery.of(context).size.height * 0.02), Text( "Emmanuel Jerry", style: GoogleFonts.poppins( textStyle: TextStyle(color: Colors.white, fontSize: MediaQuery.of(context).size.width * 0.053), ), ), Text( "HI Welcome back", style: GoogleFonts.poppins( textStyle: TextStyle(color: Colors.white, fontSize: MediaQuery.of(context).size.width * 0.037), ), ) ], ), ), ], ), ); } } // 使用方式 Scaffold( appBar: ResponsiveAppBar(), // ...其他页面内容 )
方法2:使用适配库(如flutter_screenutil)
若已在用flutter_screenutil做屏幕适配,确保初始化正确后,用相对单位设置高度和位置即可:
- 先在main函数初始化适配:
void main() { runApp( ScreenUtilInit( designSize: Size(375, 812), // 对应设计稿尺寸 minTextAdapt: true, splitScreenMode: true, child: MyApp(), ), ); }
- 自定义响应式AppBar:
class ResponsiveAppBar extends StatelessWidget implements PreferredSizeWidget { @override Size get preferredSize => Size.fromHeight(155.h); // 基于设计稿的相对高度 @override Widget build(BuildContext context) { return Container( width: double.infinity, height: preferredSize.height, child: Stack( clipBehavior: Clip.none, children: [ Image.asset('assets/topBackground.png', fit: BoxFit.cover, height: double.infinity), Positioned( left: 8.w, top: 20.h, child: SizedBox( width: MediaQuery.of(context).size.width - 16.w, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Icon(Icons.menu, color: Colors.white), CircleAvatar(child: Image.asset("assets/Emmanuel_Jerry.png")), ], ), ), ), Positioned( top: 50.h, left: 10.w, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 2.h), Text( "Emmanuel Jerry", style: GoogleFonts.poppins(textStyle: TextStyle(color: Colors.white, fontSize: 20.sp)), ), Text( "HI Welcome back", style: GoogleFonts.poppins(textStyle: TextStyle(color: Colors.white, fontSize: 14.sp)), ) ], ), ), ], ), ); } }
注意事项
- 避免直接在默认
AppBar的bottom属性中嵌套大高度PreferredSize,否则会和默认AppBar的kToolbarHeight叠加,导致整体高度超出预期。直接自定义PreferredSizeWidget替换默认AppBar更可控。 - 所有元素的位置、尺寸都需使用相对单位(MediaQuery比例或适配库单位),禁止使用固定像素值。
内容的提问来源于stack exchange,提问作者SAFI Ullah
相关产品推荐
相关产品推荐

