我是一个新的Flutter动画,我有一个秒表屏幕,其中有一个包含秒表的容器,一个包含圈数列表的容器,以及3个浮动的动作按钮,它们可以做三件事,重置,播放暂停和圈数。我希望秒表容器在单击圈数按钮时向上动画,然后在单击重置按钮时向下动画。
第一次
class _StopWatchScreenState extends State<StopWatchScreen>
with SingleTickerProviderStateMixin {
final StopWatchTimer _stopWatchTimer = StopWatchTimer();
final _isHours = true;
late AnimationController controller;
bool isPlaying = false;
bool lapClicked = false;
double value = 150.0;
final ScrollController scrollController = ScrollController();
@override
void initState() {
super.initState();
controller =
AnimationController(vsync: this, duration: Duration(milliseconds: 200));
}
void dispose() {
super.dispose();
_stopWatchTimer.dispose();
scrollController.dispose();
controller.dispose();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Column(
children: [
Center(
child: Padding(
padding: EdgeInsets.only(top: value), // Issue here
child: AnimatedContainer(
child: Center(
child: StreamBuilder<int>(
stream: _stopWatchTimer.rawTime,
initialData: _stopWatchTimer.rawTime.value,
builder: (context, snapshot) {
final value = snapshot.data;
final displayTime = StopWatchTimer.getDisplayTime(
value!,
hours: _isHours);
return Text(
displayTime,
style: GoogleFonts.lato(
fontSize: 40.0, color: Colors.white),
);
})),
width: 350.0,
height: 450.0,
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 5.0),
shape: BoxShape.circle),
duration: const Duration(milliseconds: 100),
curve: Curves.fastLinearToSlowEaseIn,
),
),
),
Visibility(
visible: lapClicked,
child: Container(
height: 280.0,
child: StreamBuilder<List<StopWatchRecord>>(
stream: _stopWatchTimer.records,
initialData: _stopWatchTimer.records.value,
builder: (context, snapshot) {
final value = snapshot.data;
if (value!.isEmpty) {
return Container();
}
Future.delayed(const Duration(milliseconds: 100), () {
scrollController.animateTo(
scrollController.position.maxScrollExtent,
duration: Duration(milliseconds: 200),
curve: Curves.easeOut);
});
return ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: value.length,
itemBuilder: (context, index) {
final data = value[index];
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(left: 20.0),
child: Text(
'Lap ${index + 1}',
style: GoogleFonts.lato(
fontSize: 30.0, color: Colors.white70),
),
),
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: Text('${data.displayTime}',
style: GoogleFonts.lato(
fontSize: 30.0,
color: Colors.white70)),
)
],
),
const Padding(
padding: EdgeInsets.only(top: 5.0),
child: Opacity(
opacity: 0.1,
child: Divider(
thickness: 1.5,
color: Colors.white70,
),
),
)
],
);
},
controller: scrollController,
);
},
),
),
),
],
),
floatingActionButton: Padding(
padding: const EdgeInsets.only(left: 30.0, bottom: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
FloatingActionButton(
onPressed: () {
setState(() {
lapClicked = false;
value = 190.0;
});
controller.reverse();
_stopWatchTimer.onExecute.add(StopWatchExecute.reset);
},
child: const Icon(
Icons.refresh,
size: 30.0,
),
),
FloatingActionButton(
onPressed: () {
toggleIcon();
if (isPlaying == true) {
_stopWatchTimer.onExecute.add(StopWatchExecute.start);
} else {
_stopWatchTimer.onExecute.add(StopWatchExecute.stop);
}
},
child: AnimatedIcon(
icon: AnimatedIcons.play_pause,
size: 35.0,
progress: controller,
),
),
FloatingActionButton(
onPressed: () {
setState(() {
lapClicked = true;
value = 10.0;
});
_stopWatchTimer.onExecute.add(StopWatchExecute.lap);
},
child: const Icon(
Icons.timer,
size: 30.0,
),
),
],
),
),
),
);
}
void toggleIcon() {
setState(() {
isPlaying = !isPlaying;
isPlaying ? controller.forward() : controller.reverse();
});
}
}
2条答案
按热度按时间lnlaulya1#
使用具有可见性的动画容器
请参阅动画容器
Animated Container
rggaifut2#
我使用
AnimatedContainer
来设置秒表的动画,并通过从容器中删除padding
属性并将其替换为margin
属性来修复动画问题