在可扩展浮动操作按钮中,在颤动中未检测到子小部件中的手势
Posted
技术标签:
【中文标题】在可扩展浮动操作按钮中,在颤动中未检测到子小部件中的手势【英文标题】:In Expandable Floating action button the gestures in the child widget is not detected in flutter 【发布时间】:2021-09-24 01:39:54 【问题描述】:尝试实现一个二维扩展的浮动操作按钮,然后显示更多浮动操作按钮选项。 不知何故,能够使用变换小部件将浮动操作按钮的子小部件设置为正确的位置,但是当我尝试按下子小部件时,即按下浮动操作按钮时出现的小部件,它们没有响应到 onPressed 处理程序。 尝试了许多不同的东西,如 IgnorePointer、堆叠的行和列、AnimatedBuilder 等。但无法找到正确的解决方案。 就像有时用来使 UI 正确,然后未检测到手势,如果检测到手势,则 UI 会失真。 而且我对扑腾有点陌生。如有任何帮助解决此问题,我们将不胜感激。
这是我的代码:
main.dart
import "package:flutter/material.dart";
import 'myhome.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
theme: ThemeData(
primaryColor: Colors.blue,
),
title: "Custom Expandable FAB",
home: MyHome(),
);
myhome.dart
import 'package:flutter/material.dart';
import 'package:tester_project/customFAB.dart';
class MyHome extends StatelessWidget
@override
Widget build(BuildContext context)
return Scaffold(
extendBody: true,
backgroundColor: Colors.white,
floatingActionButton: CustomFab(),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomAppBar(
color: Colors.blue,
shape: CircularNotchedRectangle(),
child: Container(
height: 55,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
icon: Icon(Icons.search),
onPressed: () ,
),
IconButton(
icon: Icon(Icons.menu),
onPressed: () ,
),
],
),
),
),
appBar: AppBar(
title: Text("Custom FAB"),
),
body: Container(
alignment: Alignment.center,
child: Text("Click on Fab to expand"),
color: Colors.white,
),
);
CustomFab.dart
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
class CustomFab extends StatefulWidget
@override
_CustomFabState createState() => _CustomFabState();
class _CustomFabState extends State<CustomFab>
with SingleTickerProviderStateMixin
AnimationController _animationController;
Animation<double> _translateAnimation;
Animation<double> _rotationAnimation;
Animation<double> _iconRotation;
bool _isExpanded = false;
void animate()
if (!_isExpanded)
_animationController.forward();
else
_animationController.reverse();
_isExpanded = !_isExpanded;
Widget fab1()
return Container(
height: 60,
width: 60,
child: FittedBox(
child: FloatingActionButton(
heroTag: "btn3",
backgroundColor: Color(0xffFFC852),
elevation: 0,
onPressed: ()
print("pressed");
,
),
),
);
Widget fab2()
return Container(
height: 60,
width: 60,
child: FittedBox(
child: FloatingActionButton(
heroTag: "btn4",
child: Transform.rotate(
angle: _iconRotation.value,
child: Icon(Icons.home),
),
elevation: _isExpanded ? 5 : 0,
backgroundColor: Color(0xffE5E4F4),
onPressed: ()
print("Pressed");
,
),
),
);
Widget fab3()
return Container(
height: 60,
width: 60,
child: FittedBox(
child: FloatingActionButton(
heroTag: "btn5",
child: Transform.rotate(
angle: _rotationAnimation.value,
child: Icon(Icons.add),
),
backgroundColor: Color(0xffFFC852),
onPressed: () async
await Permission.contacts.request();
if (await Permission.contacts.status.isGranted)
animate();
,
),
),
);
@override
void initState()
_animationController =
AnimationController(vsync: this, duration: Duration(milliseconds: 400))
..addListener(()
setState(() );
);
_translateAnimation = Tween<double>(begin: 0, end: 80)
.chain(
CurveTween(
curve: _isExpanded ? Curves.fastOutSlowIn : Curves.bounceOut,
),
)
.animate(_animationController);
_iconRotation = Tween<double>(begin: 3.14 / 2, end: 0)
.chain(
CurveTween(curve: Curves.bounceInOut),
)
.animate(_animationController);
_rotationAnimation = Tween<double>(begin: 0, end: 3 * 3.14 / 4)
.chain(
CurveTween(
curve: Curves.bounceInOut,
),
)
.animate(_animationController);
super.initState();
@override
void dispose()
_animationController.dispose();
super.dispose();
@override
Widget build(BuildContext context)
return Stack(
clipBehavior: Clip.none,
children: [
Transform(
transform:
Matrix4.translationValues(0, -_translateAnimation.value, 0),
child: fab1(),
),
Transform(
transform:
Matrix4.translationValues(-_translateAnimation.value, 0, 0),
child: fab2(),
),
fab3(),
],
);
展开前后的浮动动作按钮
【问题讨论】:
【参考方案1】:看看这个。 https://api.flutter.dev/flutter/widgets/Transform-class.html
与在布局之前应用旋转的 RotatedBox 不同,此对象仅在绘制之前应用其转换,这意味着在计算此小部件的子级(以及此小部件)消耗多少空间时不考虑转换。
所以,您的fab1(),fab2(),fab3()
的位置相同。
尽管您为它们设置了动画,但它只是在painting
处移动,它们的真实位置不会改变。
只要给你的工厂上色,你就会明白我的意思。
Container(
color:Colors.green,
child: Transform(
transform:
Matrix4.translationValues(-_translateAnimation!.value, 0, 0),
child: fab2(),
),
),
现在您知道原因了,而且您需要知道怎么做。
所以我希望你能看看这个。 https://api.flutter.dev/flutter/animation/animation-library.html
您可以使用Stack&&Positioned
,和Tween
,计算每个按钮的位置,或其他方式。我会让你去探索。
这是 CustomFab.dart 的一些代码
@override
Widget build(BuildContext context)
return Container(
// color: Colors.green, // Give this area a background color, then you know why.
height: 150,// You need to give your "action area" a bigger size.
width: 150,// make these bigger have a problem, your bar will have a bigger circle.
// if you need this effect, you need to change all your fabs "Stack on the appbar"
// or just remove `shape: CircularNotchedRectangle(),` in myhome.dart
child: Stack(
clipBehavior: Clip.none,
children: [
Positioned(// These numbers just for example, you can make your own size or position.
left: 150 / 2 - 30,
bottom: _translateAnimation.value + 40,
child: fab1(),
),
Positioned(
left: 150 / 2 - 30 -_translateAnimation.value,
bottom: 40,
child: fab2(),
),
Positioned(
left: 150 / 2 - 30,
bottom: 40,
child: fab3(),
),
],
),
);
【讨论】:
我也尝试使用堆栈和定位小部件来实现它,但没有任何改变,一切都保持不变...... 如果可能的话,请用不同的方法帮助我...... 在您的情况下,还有一个问题是,您的堆栈大小很小,而您clipBehavior: Clip.none,
,因此按钮可以绘制,但没有手势区域。我会编辑答案。
关于if you need this effect, you need to change all your fabs "Stack on the appbar"
,我的意思是,不要在 CustomFab 中创建 floating buttons
,您可以创建 Overlay
,使按钮浮动在屏幕上,计算他们的位置。【参考方案2】:
使用此套餐https://pub.dev/packages/flutter_speed_dial尝试快速拨号
SpeedDial(
marginBottom: 25,
marginEnd: 25,
backgroundColor: Colors.blue,
activeBackgroundColor: Colors.white,
activeForegroundColor: Colors.blue,
animatedIcon: AnimatedIcons.menu_close,
children: [
SpeedDialChild(
child: Icon(
Icons.filter_alt,
),
label: 'ABC',
onTap: ()
),
SpeedDialChild(
labelBackgroundColor: Colors.white,
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
child: Icon(Icons.add),
label: 'ABC',
onTap: ()
),
],
),
【讨论】:
以上是关于在可扩展浮动操作按钮中,在颤动中未检测到子小部件中的手势的主要内容,如果未能解决你的问题,请参考以下文章