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,
          ),
        ),
    );
  }
}

运行效果如下:

 

posted on 2021-12-29 09:25  小小程序员的梦想  阅读(660)  评论(0编辑  收藏  举报

导航