Mus*_*man 2 dart flutter flutter-animation
我想在Flutter中创建一个放射状菜单,并希望我的菜单按钮每次按下时都有一个旋转动画.我跟随TensorProgramming在Youtube上关于Flutter动画基础知识的教程但由于某种原因我的动画不起作用.下面我已经包含了我的RadialMenuWidget的代码.
我已经正确处理了动画控制器,使用SingleTickerProviderStateMixin扩展了小部件的状态.PS我正在模拟器上运行,当我热重新加载时,图标的旋转有时会发生变化.
任何帮助将深表感谢!
import 'package:flutter/material.dart';
import 'package:savings/utils/colors.dart';
import 'package:savings/widgets/themed_radial_menu_item.dart';
class CustomThemedRadialMenu extends StatefulWidget {
final List<CustomThemedRadialMenuItem> items;
CustomThemedRadialMenu({@required this.items});
@override
_CustomThemedRadialMenuState createState() =>
_CustomThemedRadialMenuState();
}
class _CustomThemedRadialMenuState extends State<CustomThemedRadialMenu>
with SingleTickerProviderStateMixin {
Animation animationOpenClose;
AnimationController animationControllerOpenClose;
bool isOpen;
@override
void initState() {
isOpen = false;
animationControllerOpenClose =
AnimationController(duration: new Duration(seconds: 5), vsync: this);
animationOpenClose =
Tween(begin: 0.0, end: 360.0).animate(animationControllerOpenClose)
..addListener(() {
setState(() {});
});
animationControllerOpenClose.repeat();
super.initState();
}
@override
Widget build(BuildContext context) {
///A list of the items and the center menu button
final List<Widget> menuContents = <Widget>[];
for (int i = 0; i < widget.items.length; i++) {
///Menu items
menuContents.add(widget.items[1]);
///Menu Close/Open button
menuContents.add(new InkWell(
onTap: () {},
child: Container(
padding: new EdgeInsets.all(10.0),
decoration: new BoxDecoration(
color: Colors.white,
border: new Border.all(color: darkHeadingsTextColor),
shape: BoxShape.circle,
),
child: new Transform.rotate(
angle: animationControllerOpenClose.value,
child: isOpen ? new Icon(Icons.clear) : new Icon(Icons.menu)),
),
));
}
return new Stack(
alignment: Alignment.center,
children: menuContents,
);
}
@override
void dispose() {
animationControllerOpenClose.dispose();
super.dispose();
}
closeMenu() {
animationControllerOpenClose.forward();
setState(() {
isOpen = false;
});
print("RadialMenu Closed");
}
openMenu() {
animationControllerOpenClose.forward();
setState(() {
isOpen = true;
});
print("RadialMenu Opened");
}
}
Run Code Online (Sandbox Code Playgroud)
你正在做的事情有几个问题.但是快速的FYI - 如果你清理你的代码并提出封装问题,人们更有可能帮助你.这将需要删除任何未包含的类,并且最好发布可以粘贴到单个文件中并按原样运行的解决方案.
话虽这么说,我已经实现了我认为你想要做的事情.我删除了你在那里的一些东西,以便它实际构建,所以你需要重新添加它们.
您遇到的主要问题如下:
侦听器中的SetState
..addListener(() {
setState(() {});
});
Run Code Online (Sandbox Code Playgroud)这并不理想,因为它会强制整个小部件重建动画的每个刻度.这将导致非常基本的小部件出现严重的性能问题.请AnimatedBuilder改用.或者,如果您正在寻找动画结束使用的时间..addStateListener
角度在弧度上是颤动的.我没有为Pi常数导入数学,但你可能应该这样做.
你有一间抽头,它实际上并没有打电话openMenu或closeMenu,所以它绝对不会做任何事情= d.
您将动画控制器设置为重复.这意味着它将永远持续下去.
你没有把任何东西传递给animationControllerOpenClose.forward电话.这意味着它将从当前的任何位置激活到1.0状态,即使它已经是1.0.我刚刚传入0,但你可能想要做一些关于打开/关闭的事情(如果用户在动画或其他东西时点击).
(切向问题)您似乎在每个菜单小部件后添加了一个新的菜单打开/关闭按钮.这可能是你想要做的,但我想你只想添加一个.
无论如何,这是有效的例子.每次点击,它都会更改图标然后旋转.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Spinnig Menu",
theme: ThemeData(
primaryColor: Colors.red,
),
home: new Scaffold(
body: new SafeArea(
child: new Column(
children: <Widget>[new CustomThemedRadialMenu()],
),
),
),
);
}
}
class CustomThemedRadialMenu extends StatefulWidget {
@override
_CustomThemedRadialMenuState createState() => _CustomThemedRadialMenuState();
}
class _CustomThemedRadialMenuState extends State<CustomThemedRadialMenu> with SingleTickerProviderStateMixin {
Animation animationOpenClose;
AnimationController animationControllerOpenClose;
bool isOpen;
@override
void initState() {
isOpen = false;
animationControllerOpenClose = AnimationController(duration: new Duration(seconds: 5), vsync: this);
animationOpenClose = Tween(begin: 0.0, end: 3.14159 * 2).animate(animationControllerOpenClose);
super.initState();
}
@override
Widget build(BuildContext context) {
///A list of the items and the center menu button
final List<Widget> menuContents = <Widget>[];
///Menu Close/Open button
menuContents.add(new InkWell(
onTap: () {
if (isOpen) {
closeMenu();
} else {
openMenu();
}
},
child: Container(
padding: new EdgeInsets.all(10.0),
decoration: new BoxDecoration(
color: Colors.white,
border: new Border.all(color: Colors.black38),
shape: BoxShape.circle,
),
child: new AnimatedBuilder(
animation: animationControllerOpenClose,
builder: (context, child) {
return new Transform.rotate(angle: animationOpenClose.value, child: child);
},
child: isOpen ? new Icon(Icons.clear) : new Icon(Icons.menu),
)),
));
return new Stack(
alignment: Alignment.center,
children: menuContents,
);
}
@override
void dispose() {
animationControllerOpenClose.dispose();
super.dispose();
}
closeMenu() {
animationControllerOpenClose.forward(from: 0.0);
setState(() {
isOpen = false;
});
print("RadialMenu Closed");
}
openMenu() {
animationControllerOpenClose.forward(from: 0.0);
setState(() {
isOpen = true;
});
print("RadialMenu Opened");
}
}
Run Code Online (Sandbox Code Playgroud)
值得注意的是,我在AnimatedBuilder的构建函数中构建了尽可能少的小部件.在那里建造的越少,性能越好.因为图标本身不会作为旋转的一部分而改变,所以您可以简单地将其作为子项传递.
我猜这可能会出现,所以只是一个FYI - 你可以使用一个动画交叉渐变小部件来进行图标之间的转换(只需将其放入AnimatedBuilder的孩子):
new AnimatedCrossFade(
firstChild: new Icon(Icons.clear),
secondChild: new Icon(Icons.menu),
crossFadeState: isOpen ? CrossFadeState.showFirst : CrossFadeState.showSecond,
duration: Duration(milliseconds: 300)),
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4266 次 |
| 最近记录: |