Flutter架构问题/回调函数



我是Flutter的新手,有一个关于构建以下代码的问题。这是一项正在进行的工作,但它应该说明我的问题。基本上,我有一个带有启动按钮的倒计时计时器(TimerEntry(列表。然而,我想去掉计时器对象中的按钮逻辑,并将其移动到计时器列表(TimerList(中,以便在计时器1结束后启动计时器2,或在新计时器启动时停止所有其他计时器,等等。。正如我所说,我对Flutter完全陌生,我希望有人能为我指明如何做到这一点的方向。我猜是某种自定义回调函数?

import 'package:flutter/material.dart';
class TimedItem extends AnimatedWidget {
TimedItem({this.task, this.timeRemainingInSeconds})
: super(listenable: timeRemainingInSeconds);
final Animation<int> timeRemainingInSeconds;
final String task;
Widget build(BuildContext context) {
String minutes =
'${(timeRemainingInSeconds.value / 60).floor()}'.padLeft(2, '0');
String seconds = '${(timeRemainingInSeconds.value % 60)}'.padLeft(2, '0');
return ListTile(
title: Text(
'$minutes:$seconds',
style: Theme.of(context).textTheme.display2,
),
subtitle: Text(task),
);
}
}
class TimerEntry extends StatefulWidget {
final int index;
final String task;
final Duration duration;
bool currentlyActive;
TimerEntry({this.index, this.task, this.duration, this.currentlyActive});
TimerEntryState createState() => TimerEntryState();
}
class TimerEntryState extends State<TimerEntry> with TickerProviderStateMixin {
AnimationController _controller;
AnimationController get controller {
return _controller;
}
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: widget.duration,
);
}
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Flexible(
child: TimedItem(
task: widget.task,
timeRemainingInSeconds: IntTween(
begin: controller.duration.inSeconds,
end: widget.currentlyActive ? 0 : widget.duration.inSeconds,
).animate(controller)
),
),
toggleButton()
],
);
}
Widget toggleButton() {
return FloatingActionButton(
onPressed: () {
controller.forward(from: 0.0);
widget.currentlyActive = true;
},
child: widget.currentlyActive
? Icon(Icons.pause_circle_outline)
: Icon(Icons.play_circle_outline),
);
}
}
class TimerList extends StatefulWidget {
final int currentActiveTimer = 0;
/// TODO: get them from outside
final entries = <TimerEntry>[
TimerEntry(
index: 0,
task: "The first task",
duration: Duration(minutes: 3),
currentlyActive: true,
),
TimerEntry(
index: 1,
task: "Another task altogether",
duration: Duration(minutes: 1),
currentlyActive: false,
)
];
@override
_TimerListState createState() => _TimerListState();
}
class _TimerListState extends State<TimerList> {
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: widget.entries.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return TimerEntry(
task: widget.entries[index].task,
duration: widget.entries[index].duration,
currentlyActive: widget.entries[index].currentlyActive,
);
});
}
}

编辑:这是一个使用自定义回调GetTaskButton的新版本,但现在我无法访问我的动画控制器(请参阅底部的toggleButton函数(。有没有一种方法可以做到这一点而不将控制器移动到列表类?

import 'package:flutter/material.dart';
typedef Widget GetTaskButton(TimerEntry t);
class TimedItem extends AnimatedWidget {
TimedItem({this.task, this.timeRemainingInSeconds})
: super(listenable: timeRemainingInSeconds);
final Animation<int> timeRemainingInSeconds;
final String task;
Widget build(BuildContext context) {
String minutes =
'${(timeRemainingInSeconds.value / 60).floor()}'.padLeft(2, '0');
String seconds = '${(timeRemainingInSeconds.value % 60)}'.padLeft(2, '0');
return ListTile(
title: Text(
'$minutes:$seconds',
style: Theme.of(context).textTheme.display2,
),
subtitle: Text(task),
);
}
}
class TimerEntry extends StatefulWidget {
final int index;
final String task;
final Duration duration;
final GetTaskButton getButton;
bool currentlyActive;
TimerEntry({this.index, this.task, this.duration, this.currentlyActive, this.getButton});
TimerEntryState createState() => TimerEntryState();
}
class TimerEntryState extends State<TimerEntry> with TickerProviderStateMixin {
AnimationController _controller;
AnimationController get controller {
return _controller;
}
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: widget.duration,
);
}
@override
Widget build(BuildContext context) {
//    return Text("test");
return Row(
children: <Widget>[
Flexible(
child: TimedItem(
task: widget.task,
timeRemainingInSeconds: IntTween(
begin: controller.duration.inSeconds,
end: widget.currentlyActive ? 0 : widget.duration.inSeconds,
).animate(controller)
),
),
widget.getButton(widget)
],
);
}
}
class TimerList extends StatefulWidget {
final int currentActiveTimer = 0;
/// TODO: get them from outside
final entries = <TimerEntry>[
TimerEntry(
index: 0,
task: "The first task",
duration: Duration(minutes: 3),
currentlyActive: true,
),
TimerEntry(
index: 1,
task: "Another task altogether",
duration: Duration(minutes: 1),
currentlyActive: false,
)
];
@override
_TimerListState createState() => _TimerListState();
}
class _TimerListState extends State<TimerList> {
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: widget.entries.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return TimerEntry(
task: widget.entries[index].task,
duration: widget.entries[index].duration,
currentlyActive: widget.entries[index].currentlyActive,
getButton: (Widget tButton) => toggleButton(widget.entries[index]),
);
});
}
Widget toggleButton(TimerEntry t) {
return FloatingActionButton(
onPressed: () {
setState(() {
/// TODO: how to access this one?
//          t.controller.forward(from: 0.0);
t.currentlyActive = !t.currentlyActive;
});
},
child: t.currentlyActive
? Icon(Icons.pause_circle_outline)
: Icon(Icons.play_circle_outline),
);
}
}

以下是您可以做的几件事:

创建全局列表变量。

List<TimerEntry> myEntries = List<TimerEntry>();

在myEntries列表中添加值的函数。我已经对值进行了硬编码,您可以通过Arguments使其动态。

void _addTimers() {
myEntries.add(TimerEntry(
index: 0,
task: "The first task",
duration: Duration(minutes: 3),
currentlyActive: true,
));
myEntries.add(TimerEntry(
index: 1,
task: "The Second task",
duration: Duration(minutes: 3),
currentlyActive: true,
));
}

只要需要添加计时器_addTimers();,就可以调用函数

在类TimerList中,您需要定义一个构造函数来获取列表。

class TimerList extends StatefulWidget {
final int currentActiveTimer = 0;
final List<TimerEntry> entries;
TimerList({this.entries});

&最后,您需要将全局列表变量传递到初始化它的类。

body: TimerList(entries: myEntries,),

更新:编辑toggleButton((以确保它正确响应onTap((。

Widget toggleButton() {
return FloatingActionButton(
onPressed: () {
setState(() {
controller.forward(from: 0.0);
widget.currentlyActive = !widget.currentlyActive;
});
},
child: widget.currentlyActive
? Icon(Icons.pause_circle_outline)
: Icon(Icons.play_circle_outline),
);
}

更新:将动画控制器传递给定时

class _TimerListState extends State<TimerList> with TickerProviderStateMixin {
List<AnimationController> myAnimationControllers =
List<AnimationController>();
@override
void initState() {
_getControllerList();
super.initState();
}
void _getControllerList() {
widget.entries.forEach((f) {
myAnimationControllers
.add(AnimationController(vsync: this, duration: f.duration));
});
}

然后在构建中将其传递给TimerEntry:

TimerEntry(
task: widget.entries[index].task,
duration: widget.entries[index].duration,
currentlyActive: widget.entries[index].currentlyActive,
controller: myAnimationControllers[index]),
)
class TimerEntry extends StatefulWidget {
final int index;
final String task;
final Duration duration;
bool currentlyActive;
AnimationController controller;
TimerEntry({
this.index,
this.task,
this.duration,
this.currentlyActive,
this.controller,
});

最新更新