如何多次使用带动画的小部件
How can I use a widget with animation several times
我创建了一个带有动画的自定义小部件并使用了几次,但是当我尝试使用 controller.forward();动画仅适用于最后一个小部件。但是我想让我点击的小部件动画化,请帮助我如何实现它?
这是我的小部件:
import 'package:flutter/material.dart';
import 'package:project/colors.dart';//for colors
class Favourite extends StatefulWidget {
final IconData icon;
final Function function;
final Color color;
final Color bgColor;
final double width;
final double height;
final double iconSize;
Favourite({
this.icon,
this.function,
this.color = blue,
this.bgColor = white,
this.height = 45,
this.width = 45,
this.iconSize = 40,
});
@override
_FavouriteState createState() => _FavouriteState();
}
AnimationController controller;
class _FavouriteState extends State<Favourite>
with SingleTickerProviderStateMixin {
Animation<double> animation;
@override
void initState() {
super.initState();
controller = AnimationController(
vsync: this, // the SingleTickerProviderStateMixin
duration: Duration(
milliseconds: 300), // how long should the animation take to finish
value: 0.1,
upperBound: 1,
lowerBound: 0.5,
);
animation =
CurvedAnimation(parent: controller, curve: Curves.easeInOutCirc);
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
}
});
}
@override
dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
width: widget.width,
height: widget.height,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 10),
decoration: BoxDecoration(
color: widget.bgColor,
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 10,
),
],
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
child: Center(
child: ScaleTransition(
scale: animation,
child: IconButton(
onPressed: widget.function,
icon: Icon(
widget.icon,
color: widget.color,
size: widget.iconSize,
),
),
),
),
);
}
}
因此,我想为最喜欢的按钮创建一个比例不断变化的小动画。以下是我的使用方法:
class LaptopBlock extends StatefulWidget {
@override
_LaptopBlockState createState() => _LaptopBlockState();
}
class _LaptopBlockState extends State<LaptopBlock> with SingleTickerProviderStateMixin{
@override
Widget build(BuildContext context) {
return Container(
height: 380,
child: ListView.builder(
padding: EdgeInsets.all(25),
scrollDirection: Axis.horizontal,
itemCount: laptops.length,
itemBuilder: (BuildContext context, int index) { ...
Favourite(
icon: laptops[index].isLiked == true
? Icons.favorite
: Icons.favorite_border,
function: () {
setState(() {
controller.forward();
laptops[index].isLiked = !laptops[index].isLiked;
});
},
), ...
因此,当我点击第一个收藏小部件时,图标发生变化,但动画应用于 ListView.builder 中的最后一个,而不是我点击的那个。
在网上找不到答案,只好在这里问了,提前谢谢你,抱歉我的英语不好
我认为这是因为您在状态之外制作了 AnimationController class。尝试将其移动到状态 class。这样,您将为 Widget 的每个实例拥有不同的 AnimationController。
即
class _FavouriteState extends State<Favourite>
with SingleTickerProviderStateMixin {
AnimationController controller;
而不是
AnimationController controller;
class _FavouriteState extends State<Favourite>
with SingleTickerProviderStateMixin {
所以最后是代码:
import 'package:flutter/material.dart';
import 'package:visar/colors.dart';
class Favourite extends StatefulWidget {
final IconData icon;
final function;
final Color color;
final Color bgColor;
final double width;
final double height;
final double iconSize;
Favourite({
this.icon,
this.function,
this.color = blue,
this.bgColor = white,
this.height = 45,
this.width = 45,
this.iconSize = 30,
});
@override
_FavouriteState createState() => _FavouriteState();
}
class _FavouriteState extends State<Favourite>
with SingleTickerProviderStateMixin {
AnimationController controller; //placed controller inside of the class
Animation<double> animation;
@override
void initState() {
super.initState();
controller = AnimationController(
vsync: this, // the SingleTickerProviderStateMixin
duration: Duration(
milliseconds: 300), // how long should the animation take to finish
value: 0.6,
upperBound: 1,
lowerBound: 0.6,
);
animation =
CurvedAnimation(parent: controller, curve: Curves.easeInOutCirc);
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
}
});
}
@override
dispose() {
controller.dispose();
super.dispose();
}
void control() {
controller.forward();
}
@override
Widget build(BuildContext context) {
return Container(
width: widget.width,
height: widget.height,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 10),
decoration: BoxDecoration(
color: widget.bgColor,
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 10,
),
],
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
child: Center(
child: ScaleTransition(
scale: animation,
child: IconButton(
onPressed: () {
widget.function(); //this line to run custom functions on using the widget
controller.forward(); //always runs the animation
},
icon: Icon(
widget.icon,
color: widget.color,
size: widget.iconSize,
),
),
),
),
);
}
}
我创建了一个带有动画的自定义小部件并使用了几次,但是当我尝试使用 controller.forward();动画仅适用于最后一个小部件。但是我想让我点击的小部件动画化,请帮助我如何实现它? 这是我的小部件:
import 'package:flutter/material.dart';
import 'package:project/colors.dart';//for colors
class Favourite extends StatefulWidget {
final IconData icon;
final Function function;
final Color color;
final Color bgColor;
final double width;
final double height;
final double iconSize;
Favourite({
this.icon,
this.function,
this.color = blue,
this.bgColor = white,
this.height = 45,
this.width = 45,
this.iconSize = 40,
});
@override
_FavouriteState createState() => _FavouriteState();
}
AnimationController controller;
class _FavouriteState extends State<Favourite>
with SingleTickerProviderStateMixin {
Animation<double> animation;
@override
void initState() {
super.initState();
controller = AnimationController(
vsync: this, // the SingleTickerProviderStateMixin
duration: Duration(
milliseconds: 300), // how long should the animation take to finish
value: 0.1,
upperBound: 1,
lowerBound: 0.5,
);
animation =
CurvedAnimation(parent: controller, curve: Curves.easeInOutCirc);
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
}
});
}
@override
dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
width: widget.width,
height: widget.height,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 10),
decoration: BoxDecoration(
color: widget.bgColor,
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 10,
),
],
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
child: Center(
child: ScaleTransition(
scale: animation,
child: IconButton(
onPressed: widget.function,
icon: Icon(
widget.icon,
color: widget.color,
size: widget.iconSize,
),
),
),
),
);
}
}
因此,我想为最喜欢的按钮创建一个比例不断变化的小动画。以下是我的使用方法:
class LaptopBlock extends StatefulWidget {
@override
_LaptopBlockState createState() => _LaptopBlockState();
}
class _LaptopBlockState extends State<LaptopBlock> with SingleTickerProviderStateMixin{
@override
Widget build(BuildContext context) {
return Container(
height: 380,
child: ListView.builder(
padding: EdgeInsets.all(25),
scrollDirection: Axis.horizontal,
itemCount: laptops.length,
itemBuilder: (BuildContext context, int index) { ...
Favourite(
icon: laptops[index].isLiked == true
? Icons.favorite
: Icons.favorite_border,
function: () {
setState(() {
controller.forward();
laptops[index].isLiked = !laptops[index].isLiked;
});
},
), ...
因此,当我点击第一个收藏小部件时,图标发生变化,但动画应用于 ListView.builder 中的最后一个,而不是我点击的那个。
在网上找不到答案,只好在这里问了,提前谢谢你,抱歉我的英语不好
我认为这是因为您在状态之外制作了 AnimationController class。尝试将其移动到状态 class。这样,您将为 Widget 的每个实例拥有不同的 AnimationController。
即
class _FavouriteState extends State<Favourite>
with SingleTickerProviderStateMixin {
AnimationController controller;
而不是
AnimationController controller;
class _FavouriteState extends State<Favourite>
with SingleTickerProviderStateMixin {
所以最后是代码:
import 'package:flutter/material.dart';
import 'package:visar/colors.dart';
class Favourite extends StatefulWidget {
final IconData icon;
final function;
final Color color;
final Color bgColor;
final double width;
final double height;
final double iconSize;
Favourite({
this.icon,
this.function,
this.color = blue,
this.bgColor = white,
this.height = 45,
this.width = 45,
this.iconSize = 30,
});
@override
_FavouriteState createState() => _FavouriteState();
}
class _FavouriteState extends State<Favourite>
with SingleTickerProviderStateMixin {
AnimationController controller; //placed controller inside of the class
Animation<double> animation;
@override
void initState() {
super.initState();
controller = AnimationController(
vsync: this, // the SingleTickerProviderStateMixin
duration: Duration(
milliseconds: 300), // how long should the animation take to finish
value: 0.6,
upperBound: 1,
lowerBound: 0.6,
);
animation =
CurvedAnimation(parent: controller, curve: Curves.easeInOutCirc);
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
}
});
}
@override
dispose() {
controller.dispose();
super.dispose();
}
void control() {
controller.forward();
}
@override
Widget build(BuildContext context) {
return Container(
width: widget.width,
height: widget.height,
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 10),
decoration: BoxDecoration(
color: widget.bgColor,
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 10,
),
],
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
child: Center(
child: ScaleTransition(
scale: animation,
child: IconButton(
onPressed: () {
widget.function(); //this line to run custom functions on using the widget
controller.forward(); //always runs the animation
},
icon: Icon(
widget.icon,
color: widget.color,
size: widget.iconSize,
),
),
),
),
);
}
}