You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现每日8小时使用后禁用CupertinoButton的问题

解决CupertinoButton每日累计使用满8小时后禁用的问题

需求是让CupertinoButton在当日累计使用满8小时后自动禁用,8小时内可无限制点击。你之前尝试用秒数范围判断的方式没生效,问题出在两个地方:一是逻辑不对(你要的是累计使用时长,不是当前秒数区间),二是这种写法只会在Widget首次构建时计算一次,不会随时间或使用情况自动更新状态。

下面是可行的解决方案:

核心思路

  1. 用持久化存储记录每日累计使用时长,确保App重启后数据不丢失
  2. 维护按钮的可用状态,实时判断是否达到8小时上限
  3. 点击按钮时更新累计时长,并动态同步状态

具体实现步骤

1. 先添加依赖(如果没装的话)

在pubspec.yaml里加入用于本地存储的依赖:

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.2.2

2. 完整代码示例

import 'package:flutter/cupertino.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:ionicons/ionicons.dart';

// 假设这是你的页面组件
class UsageLimitedPage extends StatefulWidget {
  const UsageLimitedPage({super.key});

  @override
  State<UsageLimitedPage> createState() => _UsageLimitedPageState();
}

class _UsageLimitedPageState extends State<UsageLimitedPage> {
  int _totalUsageSeconds = 0; // 当日累计使用时长(秒)
  String _currentDate = ''; // 记录当前日期,区分不同天数
  bool _isButtonEnabled = true; // 按钮是否可用
  final int _usagePerClick = 60; // 每次点击的使用时长(这里假设1分钟,可根据实际调整)

  @override
  void initState() {
    super.initState();
    _loadSavedUsageData();
    // 每分钟检查一次状态,确保时间到了自动禁用按钮
    Future.doWhile(() async {
      await Future.delayed(const Duration(minutes: 1));
      _checkButtonStatus();
      return true;
    });
  }

  // 加载本地存储的当日使用数据
  Future<void> _loadSavedUsageData() async {
    final prefs = await SharedPreferences.getInstance();
    final today = DateTime.now().toString().split(' ')[0]; // 获取当日日期字符串,比如"2024-05-20"
    _currentDate = today;
    _totalUsageSeconds = prefs.getInt('daily_usage_$today') ?? 0;
    _checkButtonStatus();
    setState(() {});
  }

  // 判断按钮是否应该禁用
  void _checkButtonStatus() {
    const int maxDailyUsage = 8 * 60 * 60; // 8小时换算成秒
    setState(() {
      _isButtonEnabled = _totalUsageSeconds < maxDailyUsage;
    });
  }

  // 处理按钮点击逻辑
  Future<void> _onMenuButtonPressed() async {
    if (!_isButtonEnabled) return;

    // 更新累计使用时长
    setState(() {
      _totalUsageSeconds += _usagePerClick;
    });

    // 保存到本地存储
    final prefs = await SharedPreferences.getInstance();
    await prefs.setInt('daily_usage_$_currentDate', _totalUsageSeconds);

    // 执行你原本的按钮逻辑,比如打开菜单等
    // 替换成你自己的业务代码
    // ...
  }

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      child: SafeArea(
        child: Column(
          children: [
            Align(
              alignment: Alignment.centerLeft,
              child: CupertinoButton(
                onPressed: _isButtonEnabled ? _onMenuButtonPressed : null,
                minSize: 0,
                padding: const EdgeInsets.all(8),
                child: Icon(
                  Ionicons.menu,
                  // 禁用时图标变灰,提升用户感知
                  color: _isButtonEnabled ? const ColorPalette.neutral50 : CupertinoColors.inactiveGray,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

关键细节说明

  • 持久化存储:按日期存储每日数据,避免跨天累计,确保每天0点后按钮自动恢复可用
  • 状态更新:通过setState实时刷新按钮状态,定时检查确保时间到了自动禁用
  • 用户体验:禁用时图标变灰,让用户直观知道按钮不可用
  • 灵活调整:_usagePerClick可以根据实际场景修改,比如如果是记录每次使用的实际时长,可以在点击后计算真实使用时间再累加

内容的提问来源于stack exchange,提问作者Tommz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 13:35:31