Flutter应用程序中显示图像和用户反应的准确时间
问题描述:
我必须创建一个心理反应时间测试应用程序。为此,我必须准确地控制图像何时可见,并准确测量图像可见性开始和反应开始(例如点击事件)之间的延迟。 我该如何在Flutter中实现?具体而言,在同一地点显示和隐藏多个不同图像的最有效方式是什么?我如何才能准确知道点击事件的发生与真实和完全可见性的发生相关,并考虑到帧设备的速率?是否有办法对这个过程进行低级控制。通常Flutter似乎暴露了高级别的API。Flutter应用程序中显示图像和用户反应的准确时间
答
我已经做出了尝试是有可能正是你在找什么,我的逻辑如下:
- 添加监听到的图像呈现。
- 使用
Stopwatch
类,我通知我的对象在图像显示后开始计时。 - 当点击正确答案时,我停止
Stopwatch
停止计数。 - 保存我目前的分数,并继续下一个问题。
注:
- 在这个例子中,为简单起见,我没有为哪个答案是正确的,这是不是一个帐户。
- 我创建了一个新的
StatelessWidget
来保存每个问题,使用PageView.builder
也可能是一个很好的用法。
简单的例子:
import 'dart:async';
import 'package:flutter/material.dart';
int score = 0;
class TimeTest extends StatefulWidget {
Widget nextQuestionWidget; //to navigate
String question;
NetworkImage questionImage;
List<String> answers;
TimeTest(
{this.questionImage, this.question, this.answers, this.nextQuestionWidget });
@override
_TimeTestState createState() => new _TimeTestState();
}
class _TimeTestState extends State<TimeTest> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
bool _loading = true;
Stopwatch timer = new Stopwatch();
@override
void initState() {
widget.questionImage.resolve(new ImageConfiguration()).addListener((_, __) {
if (mounted) {
setState(() {
_loading = false;
});
timer.start();
}
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
appBar: new AppBar(title: new Text("Time Test"),),
body: new Container(
alignment: FractionalOffset.center,
margin: const EdgeInsets.symmetric(vertical: 15.0),
child: new Column(
children: <Widget>[
new Text(widget.question),
new Divider(height: 15.0, color: Colors.blueAccent,),
new CircleAvatar(backgroundImage: widget.questionImage,
backgroundColor: Colors.transparent,),
new Container(height: 15.0,),
new Column(
children: new List.generate(widget.answers.length, (int index) {
return new FlatButton(
onPressed:() {
///TODO
///add conditions for correct or incorrect answers
///and some manipulation on the score
timer.stop();
score = score + timer.elapsedMilliseconds;
print(score);
_scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text(
"Your answered this question in ${timer
.elapsedMilliseconds}ms")));
///Hold on before moving to the next question
new Future.delayed(const Duration(seconds: 3),() {
Navigator.of(context).push(new MaterialPageRoute(
builder: (_) => widget.nextQuestionWidget));
});
}, child: new Text(widget.answers[index]),);
}),
)
],
),),
);
}
}
class QuestionOne extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new TimeTest(question: "Which animal is in this photo?",
questionImage: new NetworkImage(
"http://cliparting.com/wp-content/uploads/2016/09/Tiger-free-to-use-clipart.png"),
answers: ["Lion", "Tiger", "Cheetah"],
nextQuestionWidget: new QuestionTwo(),);
}
}
class QuestionTwo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new TimeTest(question: "Which bird is in this photo?",
questionImage: new NetworkImage(
"http://www.clker.com/cliparts/P/q/7/9/j/q/eagle-hi.png"),
answers: ["Hawk", "Eagle", "Falcon"],
nextQuestionWidget: new ResultPage(),);
}
}
class ResultPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text("Result"),),
body: new Center(
child: new Text("CONGRATULATIONS! Your score is $score milliseconds"),),
);
}
}
void main() {
runApp(new MaterialApp(home: new QuestionOne()));
}
Grrrrrreat !!!!! – Michael
此解决方案在屏幕上推送新路线。是不是像大量路线的内存泄漏?我宁愿替换现有的图像我如何存档? – Michael
我不想使用pushReplacement,因为它取代了整个小部件。是否可以简单地只交换图像并在显示时准确通知? – Michael