在 Flutter 中创建自定义时钟小部件
Posted
技术标签:
【中文标题】在 Flutter 中创建自定义时钟小部件【英文标题】:Creating a custom clock widget in Flutter 【发布时间】:2017-07-16 15:51:04 【问题描述】:我的目标是创建一个类似的时钟。如何使用 Flutter 实现它?
【问题讨论】:
【参考方案1】:我会推荐 Layouts、Interactivity 和 Animation 教程。 codelab 也是了解 Flutter 的好方法。
这是如何构建应用程序的草图。
import 'dart:math' as math;
import 'package:meta/meta.dart';
import 'package:flutter/material.dart';
void main()
runApp(new MaterialApp(
theme: new ThemeData(
canvasColor: Colors.deepPurple,
iconTheme: new IconThemeData(color: Colors.white),
accentColor: Colors.pinkAccent,
brightness: Brightness.dark,
),
home: new MyHomePage(),
));
class ProgressPainter extends CustomPainter
ProgressPainter(
@required this.animation,
@required this.backgroundColor,
@required this.color,
) : super(repaint: animation);
/// Animation representing what we are painting
final Animation<double> animation;
/// The color in the background of the circle
final Color backgroundColor;
/// The foreground color used to indicate progress
final Color color;
@override
void paint(Canvas canvas, Size size)
Paint paint = new Paint()
..color = backgroundColor
..strokeWidth = 5.0
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
canvas.drawCircle(size.center(Offset.zero), size.width / 2.0, paint);
paint.color = color;
double progressRadians = (1.0 - animation.value) * 2 * math.pi;
canvas.drawArc(
Offset.zero & size, math.pi * 1.5, -progressRadians, false, paint);
@override
bool shouldRepaint(ProgressPainter other)
return animation.value != other.animation.value ||
color != other.color ||
backgroundColor != other.backgroundColor;
class MyHomePage extends StatefulWidget
_MyHomePageState createState() => new _MyHomePageState();
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin
List<IconData> icons = <IconData>[
Icons.alarm, Icons.access_time, Icons.hourglass_empty, Icons.timer,
];
AnimationController _controller;
String get timeRemaining
Duration duration = _controller.duration * _controller.value;
return '$duration.inMinutes $(duration.inSeconds % 60)
.toString()
.padLeft(2, '0')';
@override
void initState()
super.initState();
_controller = new AnimationController(
vsync: this,
duration: const Duration(seconds: 12),
)
..reverse(from: 0.4);
Widget build(BuildContext context)
ThemeData themeData = Theme.of(context);
return new Scaffold(
body: new Padding(
padding: const EdgeInsets.all(10.0),
child:
new Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: icons.map((IconData iconData)
return new Container(
margin: new EdgeInsets.all(10.0),
child: new IconButton(
icon: new Icon(iconData), onPressed: ()
// TODO: Implement
),
);
).toList(),
),
new Expanded(
child: new Align(
alignment: FractionalOffset.center,
child: new AspectRatio(
aspectRatio: 1.0,
child: new Stack(
children: <Widget>[
new Positioned.fill(
child: new AnimatedBuilder(
animation: _controller,
builder: (BuildContext context, Widget child)
return new CustomPaint(
painter: new ProgressPainter(
animation: _controller,
color: themeData.indicatorColor,
backgroundColor: Colors.white,
),
);
),
),
new Align(
alignment: FractionalOffset.center,
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Text(
'Label', style: themeData.textTheme.subhead),
new AnimatedBuilder(
animation: _controller,
builder: (BuildContext context, Widget child)
return new Text(
timeRemaining,
style: themeData.textTheme.display4,
);
),
new Text('+1', style: themeData.textTheme.title),
],
),
),
],
),
),
),
),
new Container(
margin: new EdgeInsets.all(10.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new IconButton(icon: new Icon(Icons.delete), onPressed: ()
// TODO: Implement delete
),
new FloatingActionButton(
child: new AnimatedBuilder(
animation: _controller,
builder: (BuildContext context, Widget child)
return new Icon(
_controller.isAnimating
? Icons.pause
: Icons.play_arrow
);
,
),
onPressed: ()
if (_controller.isAnimating)
_controller.stop();
else
_controller.reverse(
from: _controller.value == 0.0 ? 1.0 : _controller
.value,
);
,
),
new IconButton(
icon: new Icon(Icons.alarm_add), onPressed: ()
// TODO: Implement add time
),
],
),
),
],
),
),
);
【讨论】:
以上是关于在 Flutter 中创建自定义时钟小部件的主要内容,如果未能解决你的问题,请参考以下文章