Flutter自定义可展开FAB子按钮点击无法触发路由跳转问题求助
问题原因
你的问题和回调类型、路由配置都无关,核心是两个布局逻辑的叠加导致点击事件无法触发:
Transform属于绘制阶段的变换,只会修改组件的渲染位置,不会调整组件的实际布局命中区域- 你内层包裹按钮的
Stack没有指定尺寸,默认会适配最大子元素的大小(也就是主FAB的60x60尺寸),所有通过Transform向上平移超出这个60x60范围的子FAB,点击位置都不在Stack的命中检测范围内,自然不会触发对应的点击回调。
解决方案
给内层Stack套上足够大的尺寸容器,让它覆盖所有子FAB展开后的区域即可,同时可以调整对齐方式更符合展开逻辑:
@override Widget build(BuildContext context) { return Stack( children: [ Positioned( right: 10, bottom: 10, // 新增SizedBox指定足够的宽高,覆盖所有子FAB展开范围 child: SizedBox( width: 80, // 适配FAB宽度+左右点击余量 height: 370, // 最大偏移300 + 主FAB高度60 + 顶部余量10 child: Stack( alignment: Alignment.bottomCenter, // 改成底部居中对齐,适配向上展开的逻辑 children: [ // 原有4个子FAB的代码保持不变 Transform.translate( offset: Offset.fromDirection(getRadiansFromDegree(270), degOneTranslationAnimation.value * 75), child: Transform( transform: Matrix4.rotationZ( getRadiansFromDegree(rotationAnimation.value)) ..scale(degOneTranslationAnimation.value), alignment: Alignment.center, child: CircularButton( color: Colors.red, width: 50, height: 50, icon: Icon( Icons.storefront, color: Colors.white, ), onClick: () { Navigator.of(context) .pushNamed(RouteGenerator.marketPage); }, ), ), ), // 剩余3个子FAB代码保持不变 Transform.translate( offset: Offset.fromDirection(getRadiansFromDegree(270), degOneTranslationAnimation.value * 150), child: Transform( transform: Matrix4.rotationZ( getRadiansFromDegree(rotationAnimation.value)) ..scale(degOneTranslationAnimation.value), alignment: Alignment.center, child: CircularButton( color: Colors.red, width: 50, height: 50, icon: Icon( Icons.phone_android, color: Colors.white, ), onClick: () { Navigator.of(context) .pushNamed(RouteGenerator.myShopPage); }, ), ), ), Transform.translate( offset: Offset.fromDirection(getRadiansFromDegree(270), degOneTranslationAnimation.value * 225), child: Transform( transform: Matrix4.rotationZ( getRadiansFromDegree(rotationAnimation.value)) ..scale(degOneTranslationAnimation.value), alignment: Alignment.center, child: CircularButton( color: Colors.red, width: 50, height: 50, icon: Icon( Icons.bookmarks_outlined, color: Colors.white, ), onClick: () { Navigator.of(context) .pushNamed(RouteGenerator.bookmarkPage); }, ), ), ), Transform.translate( offset: Offset.fromDirection(getRadiansFromDegree(270), degOneTranslationAnimation.value * 300), child: Transform( transform: Matrix4.rotationZ( getRadiansFromDegree(rotationAnimation.value)) ..scale(degOneTranslationAnimation.value), alignment: Alignment.center, child: CircularButton( color: Colors.red, width: 50, height: 50, icon: Icon( Icons.manage_search, color: Colors.white, ), onClick: () { Navigator.of(context) .pushNamed(RouteGenerator.searchPage); }, ), ), ), // 原有主FAB代码保持不变 Transform( transform: Matrix4.rotationZ( getRadiansFromDegree(rotationAnimation.value)), alignment: Alignment.center, child: CircularButton( color: Colors.red, width: 60, height: 60, icon: Icon( Icons.menu, color: Colors.white, ), onClick: () { if (animationController.isCompleted) { animationController.reverse(); } else { animationController.forward(); } }, ), ), ], ), ), ) ], ); }
可选优化
你代码中定义的degTwoTranslationAnimation、degThreeTranslationAnimation两个动画变量没有实际使用,可以直接删除减少冗余代码。如果需要防止子FAB未完全展开时的误触,可以给所有子FAB套上IgnorePointer组件,当animationController.isCompleted为false时禁用点击即可。
内容的提问来源于stack exchange,提问作者Omnilol
相关产品推荐
相关产品推荐

