文章

Flutter实现IOS时间选择轮盘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import 'package:flutter/material.dart';

/// 倒计时数字样式
TextStyle countdownStyle = const TextStyle(
  fontFamily: 'Microsoft Yahei',
  fontSize: 80,
  fontWeight: FontWeight.w900,
  letterSpacing: 6,
);

/// 倒计时设置组件
///
/// 用于设置倒计时的时分秒,通过轮盘选择器实现
class CountdownSet extends StatefulWidget {
  final int allSeconds; // 总秒数
  final Function setSeconds; // 设置秒数的回调函数

  const CountdownSet(this.allSeconds, this.setSeconds, {super.key});

  @override
  State<CountdownSet> createState() => _CountdownSetState();
}

class _CountdownSetState extends State<CountdownSet> {
  late int hour; // 小时
  late int minute; // 分钟
  late int second; // 秒

  @override
  void initState() {
    super.initState();
    // 初始化时分秒
    hour = widget.allSeconds ~/ 3600; // 计算小时数
    minute = (widget.allSeconds % 3600) ~/ 60; // 计算分钟数
    second = widget.allSeconds % 60; // 计算秒数
  }

  /// 更新总秒数
  ///
  /// 将当前的时分秒转换为总秒数,并通过回调函数传递给父组件
  void _updateTotalSeconds() {
    int totalSeconds = hour * 3600 + minute * 60 + second;
    widget.setSeconds(totalSeconds);
  }

  /// 构建轮盘选择器
  ///
  /// [items] 可选数字列表
  /// [value] 当前选中的值
  /// [onChanged] 值改变时的回调函数
  Widget _buildScrollWheel(
    List<int> items,
    int value,
    Function(int) onChanged,
  ) {
    return SizedBox(
      width: 130,
      height: 120,
      child: ListWheelScrollView(
        itemExtent: 100, // 每个选项的高度
        diameterRatio: 1.5, // 轮盘的直径比例
        useMagnifier: true, // 使用放大镜效果
        magnification: 1, // 放大倍数
        controller: FixedExtentScrollController(
          initialItem: items.indexOf(value), // 设置初始选中项
        ),
        onSelectedItemChanged: (index) {
          onChanged(items[index]); // 值改变时调用回调函数
          _updateTotalSeconds(); // 更新总秒数
        },
        children: items.map((item) {
          return Center(
            child: Text(
              item.toString().padLeft(2, '0'), // 补零显示两位数
              style: countdownStyle,
            ),
          );
        }).toList(),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        // 小时选择器
        _buildScrollWheel(
          List.generate(24, (index) => index), // 0-23小时
          hour,
          (value) => setState(() => hour = value),
        ),
        Text(':', style: countdownStyle),
        // 分钟选择器
        _buildScrollWheel(
          List.generate(60, (index) => index), // 0-59分钟
          minute,
          (value) => setState(() => minute = value),
        ),
        Text(':', style: countdownStyle),
        // 秒数选择器
        _buildScrollWheel(
          List.generate(60, (index) => index), // 0-59秒
          second,
          (value) => setState(() => second = value),
        ),
      ],
    );
  }
}
本文由作者按照 CC BY 4.0 进行授权