Flutter带悬浮按钮底部导航栏自定义圆角挖孔形状实现问题
问题原因
你当前的实现是直接对底部导航栏整体做圆角后挖去正圆形区域,挖孔边缘和导航栏主体的衔接处没有过渡圆角,才会出现棱角明显的问题。想要实现FAB和导航栏衔接位置的顺滑圆弧效果,需要手动绘制带过渡圆角的路径,不能直接用两个路径求差集实现挖孔。
修改后的自定义形状代码
class MyBorderShape extends ShapeBorder { // 挖孔的过渡圆角大小,可自行调整 final double transitionRadius; // 挖孔直径,要比FAB实际直径大8-12左右留空隙 final double holeSize; MyBorderShape({ this.transitionRadius = 16, this.holeSize = 70, }); @override EdgeInsetsGeometry get dimensions => EdgeInsets.zero; @override Path getInnerPath(Rect rect, {TextDirection? textDirection}) => Path(); @override Path getOuterPath(Rect rect, {TextDirection? textDirection}) { final halfWidth = rect.width / 2; final halfHole = holeSize / 2; // 挖孔最顶部的Y坐标 final holeTopY = rect.top - (holeSize / 2); // 导航栏的全局圆角 final globalRadius = Radius.circular(rect.height / 2.5); Path path = Path(); // 左下角圆弧 path.moveTo(rect.left, rect.bottom - globalRadius.y); path.arcToPoint( Offset(rect.left + globalRadius.x, rect.bottom), radius: globalRadius, ); // 底部边 path.lineTo(rect.right - globalRadius.x, rect.bottom); // 右下角圆弧 path.arcToPoint( Offset(rect.right, rect.bottom - globalRadius.y), radius: globalRadius, ); // 右侧边 path.lineTo(rect.right, rect.top + globalRadius.y); // 右上角圆弧 path.arcToPoint( Offset(rect.right - globalRadius.x, rect.top), radius: globalRadius, ); // 右侧到挖孔右过渡点的直线 path.lineTo(halfWidth + halfHole + transitionRadius, rect.top); // 挖孔右过渡圆角 path.arcToPoint( Offset(halfWidth + halfHole, rect.top + transitionRadius), radius: Radius.circular(transitionRadius), clockwise: false, ); // 挖孔右半圆弧 path.arcToPoint( Offset(halfWidth - halfHole, rect.top + transitionRadius), radius: Radius.circular(halfHole), center: Offset(halfWidth, holeTopY + halfHole), ); // 挖孔左过渡圆角 path.arcToPoint( Offset(halfWidth - halfHole - transitionRadius, rect.top), radius: Radius.circular(transitionRadius), clockwise: false, ); // 左侧到左上角的直线 path.lineTo(rect.left + globalRadius.x, rect.top); // 左上角圆弧 path.arcToPoint( Offset(rect.left, rect.top + globalRadius.y), radius: globalRadius, ); path.close(); return path; } @override void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {} @override ShapeBorder scale(double t) => this; }
使用说明
- 在
BottomAppBar组件中直接指定shape为MyBorderShape即可 - 可根据你的FAB实际尺寸调整
holeSize和transitionRadius参数,实现不同的圆润效果 - 需要同步将
Scaffold的floatingActionButtonLocation属性设置为FloatingActionButtonLocation.centerDocked,保证FAB位置和挖孔对齐
内容的提问来源于stack exchange,提问作者jamesbug
相关产品推荐
相关产品推荐

