Flutter 135: 图解 Timer & ACETimerButton 自定义计时器按钮

简介: 0 基础学习 Flutter,第一百三十五步:简单自定义 ACETimerButton 倒计时按钮!

    小菜在学习 Flutter 过程中,可能会遇到倒计时等需求,此时需要用到 Timer 计时器,小菜简单尝试一下;

Timer

    Timer 作为一个抽象类,提供了两种工厂方法进行调用;可以作为一次或者重复触发的倒计时计时器;

案例尝试

1. Timer()

factory Timer(Duration duration, void Function() callback) {
    if (Zone.current == Zone.root) {
      return Zone.current.createTimer(duration, callback);
    }
    return Zone.current.createTimer(duration, Zone.current.bindCallbackGuarded(callback));
}

    Timer 允许指定延迟时间之后执行,通过设置 Timeout 来指定延迟时间,之后通过 callback 回调对执行结果进行监听处理;

Timer(Duration(seconds: 3), () {
  print("_timer01() -> Timer(Duration(seconds: 3) printed after 3 seconds");
  Toast.show('Timer(Duration(seconds: 3) printed after 3 seconds !', context,
      duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
});

2. Timer.periodic()

factory Timer.periodic(Duration duration, void callback(Timer timer)) {
    if (Zone.current == Zone.root) {
      return Zone.current.createPeriodicTimer(duration, callback);
    }
    var boundCallback = Zone.current.bindUnaryCallbackGuarded<Timer>(callback);
    return Zone.current.createPeriodicTimer(duration, boundCallback);
}

    简单了解 Timer.periodic() 命名构造方法可得,该命名构造方法通过定时绑定回调进行再次 Timer 倒计时处理;

    Timer.periodic() 可以重复性、周期性的进行倒计时,若不进行手动调用,则会一直关闭,即便页面关闭也会继续调用;

    其中 Timer.tick 为调用次数,Timer.isActive 代表当前 Timer 是否处于活跃状态;

Timer.periodic(Duration(seconds: 2), (timer) {
  print('_timer02() -> Timer.periodic() -> Timer.tick -> ${timer.tick} -> Timer.isActive -> ${timer.isActive}');
});

3. Timer.run()

static void run(void Function() callback) {
    new Timer(Duration.zero, callback);
}

    Timer 的执行为异步操作,Flutter 提供了便利的 Timer.run() 命名构造函数可以方便尽快执行,可以简单理解为倒计时为 0

    小菜尝试了如下操作顺序,首先执行同步的 A -> B -> C,之后才会是异步的 run() 和 Duration.zero

print('_timer03() -> A');
Timer.run(() {
  print('_timer03() -> Timer.run()');
});
print('_timer03() -> B');
Timer(Duration.zero, () {
  print('_timer03() -> Duration.zero');
});
print('_timer03() -> C');

4. cancel()

    Timer() 计时器可以通过 cancel() 来取消,尤其是在进行周期性的 Timer.periodic() 调用时,需要在合适的时机及时取消;小菜尝试在 Timer() 回调内取消和方法外回调两种方式;

4.1 Timer() 回调内取消
Timer.periodic(Duration(seconds: 2), (timer) {
  if (timer.tick == 3) {
    timer.cancel();
  }
  print('_timer04() -> Timer.periodic() -> Timer.tick -> ${timer.tick} -> Timer.isActive -> ${timer.isActive}');
});

4.2 方法外取消
_timer = Timer.periodic(Duration(seconds: 2), (timer) {
  print('_timer05() -> Timer.periodic() -> Timer.tick -> ${timer.tick} -> Timer.isActive -> ${timer.isActive}');
});

_timer.cancel();

ACETimerButton 自定义计时器

    小菜尝试了一个简单的计时器,类似于获取验证码按钮;timeout 为倒计时时长,color 用于自定义文本颜色,preName 为文本内容;

ACETimerButton(this.timeout, {this.color, this.preName});

    整个定义过程很简单,只需在按钮点击时更新按钮文本内容以及进行 Timer 周期性倒计时计算,并在倒计时结束和 Widget 销毁时及时取消并销毁 Timer 即可;

class ACETimerButton extends StatefulWidget {
  final int timeout;
  final Color color;
  final String preName;

  ACETimerButton(this.timeout, {this.color, this.preName});

  @override
  _ACETimerButtonState createState() => _ACETimerButtonState();
}

class _ACETimerButtonState extends State<ACETimerButton> {
  Timer _timer;
  int _timeOut;
  String _name;
  bool _isClick = false;

  @override
  Widget build(BuildContext context) => GestureDetector(
      onTap: () {
        if (!_isClick) {
          _startTimer();
        }
        _isClick = true;
      },
      child: Container(
          padding: EdgeInsets.all(6.0),
          decoration: BoxDecoration(
              color: Colors.grey.withOpacity(0.2),
              borderRadius: BorderRadius.circular(4.0)),
          child: Center(child: Text(_name ?? 'click', style: TextStyle(color: widget.color ?? Colors.blue, fontSize: 16.0)))));

  @override
  void initState() {
    super.initState();
    _name = widget.preName;
    _timeOut = widget.timeout;
  }

  _startTimer() {
    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
      setState(() {
        _timeOut--;
        _name = '$_timeOut s';
      });
      if (_timeOut == 0) {
        _cancelTimer();
        _isClick = false;
        _name = widget.preName;
        _timeOut = widget.timeout;
      }
    });
  }

  _cancelTimer() {
    if (_timer != null) {
      _timer.cancel();
      _timer = null;
    }
    _isClick = false;
  }

  @override
  void dispose() {
    super.dispose();
    _cancelTimer();
  }
}


    Timer 案例源码


    小菜对 Timer 计时器的学习暂时告一段落,对于 ACETimerButton 自定义计时器按钮还不够完善;如有错误,请多多指导!

来源: 阿策小和尚
目录
相关文章
|
7月前
|
缓存 Java 开发工具
Flutter的文本、图片和按钮使用
Flutter的文本、图片和按钮使用
68 0
|
4天前
|
前端开发 搜索推荐 开发者
【Flutter前端技术开发专栏】Flutter中的自定义主题与暗黑模式
【4月更文挑战第30天】本文介绍了如何在Flutter中自定义主题和实现暗黑模式。通过`ThemeData`类定义应用的外观,包括颜色、字体和样式。示例展示了如何设置主色、强调色及文本、按钮主题。暗黑模式可通过`darkTheme`属性启用,结合`ThemeData.dark()`方法定制。利用`MediaQuery`监听系统亮度变化,动态调整暗黑模式状态。Flutter的这些特性有助于开发者创建独特且用户友好的界面。
【Flutter前端技术开发专栏】Flutter中的自定义主题与暗黑模式
|
4天前
|
缓存 前端开发 搜索推荐
【Flutter前端技术开发专栏】Flutter中的自定义绘制与Canvas API
【4月更文挑战第30天】Flutter允许开发者通过`CustomPaint`和`CustomPainter`进行自定义绘制,以实现丰富视觉效果。`CustomPaint` widget将`CustomPainter`应用到画布,而`CustomPainter`需实现`paint`和`shouldRepaint`方法。`paint`用于绘制图形,如示例中创建的`MyCirclePainter`绘制蓝色圆圈。Canvas API提供绘制形状、路径、文本和图片等功能。注意性能优化,避免不必要的重绘和利用缓存提升效率。自定义绘制让Flutter UI更具灵活性和个性化,但也需要图形学知识和性能意识。
【Flutter前端技术开发专栏】Flutter中的自定义绘制与Canvas API
|
4天前
|
开发框架 前端开发 搜索推荐
【Flutter前端技术开发专栏】Flutter中的自定义Widget与渲染流程
【4月更文挑战第30天】探索Flutter的自定义Widget与渲染流程。自定义Widget是实现复杂UI设计的关键,优点在于个性化设计、功能扩展和代码复用,但也面临性能优化和复杂性管理的挑战。创建步骤包括设计结构、定义Widget类、实现构建逻辑和处理交互。Flutter渲染流程涉及渲染对象树、布局、绘制和合成阶段。实践案例展示如何创建带渐变背景和阴影的自定义按钮。了解这些知识能提升应用体验并应对开发挑战。查阅官方文档以深入学习。
【Flutter前端技术开发专栏】Flutter中的自定义Widget与渲染流程
|
4天前
|
前端开发 开发者 UED
Flutter的自定义Painter:深入探索自定义绘制Widget的技术实现
【4月更文挑战第26天】Flutter的自定义Painter允许开发者根据需求绘制独特UI,通过继承`CustomPaint`类和重写`paint`方法实现。在`paint`中使用`Canvas`绘制图形、路径等。创建自定义Painter类后,将其作为`CustomPaint` Widget的`painter`属性使用。此技术可实现自定义形状、渐变、动画等复杂效果,提升应用视觉体验。随着Flutter的进化,自定义Painter将提供更丰富的功能。
|
4天前
|
运维 监控 定位技术
应用研发平台EMAS常见问题之flutter插件不支持自定义图标如何解决
应用研发平台EMAS(Enterprise Mobile Application Service)是阿里云提供的一个全栈移动应用开发平台,集成了应用开发、测试、部署、监控和运营服务;本合集旨在总结EMAS产品在应用开发和运维过程中的常见问题及解决方案,助力开发者和企业高效解决技术难题,加速移动应用的上线和稳定运行。
81 0
|
4天前
|
前端开发
Flutter笔记:光影动画按钮、滚动图标卡片组等
Flutter笔记:光影动画按钮、滚动图标卡片组等
42 0
|
4天前
|
iOS开发
Flutter 组件(三)按钮类组件
Flutter 组件(三)按钮类组件
169 0
|
4天前
Flutter 自定义ICON库
Flutter 自定义ICON库 Flutter提供了一些内置的ICON库,但在实际开发中,可能需要一些自定义的ICON图标。Flutter允许我们使用自定义图标,本文将介绍如何创建和使用自定义ICON库。
|
4天前
|
UED
Flutter之自定义路由切换动画
Flutter之自定义路由切换动画 在Flutter中,我们可以通过Navigator来实现路由管理,包括路由的跳转和返回等。默认情况下,Flutter提供了一些简单的路由切换动画,但是有时候我们需要自定义一些特殊的动画效果来提高用户体验。本文将介绍如何在Flutter中实现自定义的路由切换动画。