Flutter 制作旋转的秒针数字 定时器 Timer 、Transform.rotate 使用
代码如下:
import 'package:flutter/material.dart'; import 'dart:async'; import 'dart:math' as math; void main() => runApp(const ClockApp()); class ClockApp extends StatelessWidget { const ClockApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Clock', home: Container( width: 500, height: 500, margin: const EdgeInsets.all(20), child: Align( child: Stack( children: const [ SecondHandWidget(), ], ) ), ), ); } } class SecondHandWidget extends StatefulWidget { const SecondHandWidget({Key? key}) : super(key: key); @override _SecondHandWidgetState createState() => _SecondHandWidgetState(); } class _SecondHandWidgetState extends State<SecondHandWidget> { final _widgetList = <Widget>[]; // 当前时间秒数 var _second = 0; // 字体样式 final textStyle = const TextStyle( fontSize: 22, fontWeight: FontWeight.normal, color: Colors.red, decoration: TextDecoration.none, ); // 定时器 Timer? _timer; // 初始化定时器 void _initTimer() { _timer = Timer.periodic(const Duration(milliseconds: 100), (timer) { _updateSecondHand(); }); } // 初始化数字 void _initWidget() { for(int i = 0; i < 60; i++) { _widgetList.add( Align( alignment: AlignmentDirectional.center, child: Transform.rotate( angle: - math.pi / 180 * ((i - _second) * 6), child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ SizedBox( width: 30, child: Text( (i + 1).toString(), textAlign: TextAlign.center, style: textStyle, ), ), ], ), ), ) ); } } // 更新当前秒 void _updateSecondHand() { setState(() { _second = DateTime.now().second; }); } @override void initState() { _initWidget(); _initTimer(); super.initState(); } @override void dispose() { // 取消定时器 _timer?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return SizedBox( width: 700, height: 700, child: Transform.rotate( // math.pi / 180 = 旋转一度需要的角度 // math.pi / 180 * 6 秒针一格对应的角度 (360° / 60秒 = 每秒6°) // 此处根据当前秒计算出旋转的角度 angle: - math.pi / 180 * ((1-_second) * 6), child: Stack( children: _widgetList, ), ), ); } }
运行效果如下: