如何在Flutter的AppBar组件中创建内圆角效果?
在Flutter的AppBar中实现内圆角效果
要实现AppBar底部的内圆角效果,你可以通过自定义PreferredSizeWidget结合裁剪组件或背景叠加的方式完成,以下是几种实用方案:
方案一:使用ClipRRect快速实现
直接用ClipRRect裁剪AppBar的底部圆角,代码简单易上手:
class RoundedInnerAppBar extends StatelessWidget with PreferredSizeWidget { final String title; const RoundedInnerAppBar({super.key, required this.title}); @override Size get preferredSize => const Size.fromHeight(kToolbarHeight); @override Widget build(BuildContext context) { return ClipRRect( borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20), ), child: AppBar( title: Text(title), backgroundColor: Colors.blue, elevation: 0, // 关闭默认阴影避免裁剪后显示异常 ), ); } }
使用方式
在Scaffold中直接替换默认AppBar:
Scaffold( appBar: const RoundedInnerAppBar(title: "内圆角AppBar"), body: const Center(child: Text("页面内容")), );
方案二:保留阴影的叠加实现
如果需要保留AppBar的阴影效果,可通过Stack叠加背景容器和透明AppBar:
class RoundedInnerAppBar extends StatelessWidget with PreferredSizeWidget { final String title; const RoundedInnerAppBar({super.key, required this.title}); @override Size get preferredSize => const Size.fromHeight(kToolbarHeight); @override Widget build(BuildContext context) { return Stack( children: [ // 带圆角和阴影的背景容器 Positioned.fill( child: Container( decoration: const BoxDecoration( color: Colors.blue, borderRadius: BorderRadius.only( bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20), ), boxShadow: [ BoxShadow( color: Colors.black26, blurRadius: 4, offset: Offset(0, 2), ) ], ), ), ), // 透明背景的AppBar内容层 AppBar( title: Text(title), backgroundColor: Colors.transparent, elevation: 0, ), ], ); } }
方案三:自定义ClipPath实现灵活形状
如果需要更复杂的自定义内圆角形状,可使用ClipPath配合自定义裁剪器:
自定义裁剪器
class InnerRoundedClipper extends CustomClipper<Path> { final double radius; const InnerRoundedClipper({this.radius = 20}); @override Path getClip(Size size) { final path = Path(); path.moveTo(0, 0); path.lineTo(size.width, 0); // 绘制右下角内圆角 path.arcToPoint( Offset(size.width, size.height - radius), radius: Radius.circular(radius), clockwise: false, ); path.lineTo(size.width, size.height); path.lineTo(0, size.height); // 绘制左下角内圆角 path.arcToPoint( Offset(0, 0), radius: Radius.circular(radius), clockwise: false, ); return path; } @override bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false; }
应用到AppBar
class RoundedInnerAppBar extends StatelessWidget with PreferredSizeWidget { final String title; const RoundedInnerAppBar({super.key, required this.title}); @override Size get preferredSize => const Size.fromHeight(kToolbarHeight); @override Widget build(BuildContext context) { return ClipPath( clipper: const InnerRoundedClipper(), child: AppBar( title: Text(title), backgroundColor: Colors.blue, elevation: 0, ), ); } }
内容的提问来源于stack exchange,提问作者K K Muhammed Fazil
相关产品推荐
相关产品推荐

