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

如何在Flutter中实现苹果日记App风格的iOS日期选择器(支持无Material环境函数调用)

如何在Flutter中实现苹果日记App风格的iOS日期选择器(支持无Material环境函数调用)

我明白你想要实现苹果自带日记App那种风格的iOS日期选择器,而且需要在不依赖Material组件的函数里调用——刚好你已经有了一个基于CupertinoSheet的雏形,我来帮你完善这个实现,让它完全符合需求,同时解决你遇到的无Material环境兼容问题:

完整实现代码

这个函数使用Flutter官方的Cupertino组件库,完全不需要依赖Material,并且能返回用户选中的日期,调用起来非常灵活:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

Future<DateTime?> showIOSJournalStyleDatePicker(
  BuildContext context, {
  DateTime? initialDate,
  DateTime? firstDate,
  DateTime? lastDate,
}) async {
  // 设置默认参数,避免空值问题
  final defaultInitialDate = initialDate ?? DateTime.now();
  final defaultFirstDate = firstDate ?? DateTime(2000);
  final defaultLastDate = lastDate ?? DateTime(2100);

  return showCupertinoModalPopup<DateTime?>(
    context: context,
    // 让sheet从底部弹出,符合iOS交互逻辑
    builder: (ctx) {
      DateTime selectedDate = defaultInitialDate;

      return Container(
        width: double.infinity,
        decoration: const BoxDecoration(
          color: Color.fromARGB(255, 30, 30, 30),
          borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
        ),
        child: Column(
          // 自适应内容高度,避免占满屏幕
          mainAxisSize: MainAxisSize.min,
          children: [
            // 顶部操作栏:Cancel/标题/Done
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
              child: Row(
                children: [
                  CupertinoButton(
                    padding: EdgeInsets.zero,
                    onPressed: () => Navigator.of(ctx).pop(),
                    child: const Text(
                      'Cancel',
                      style: TextStyle(
                        color: Color.fromARGB(255, 32, 95, 255),
                        fontSize: 16,
                      ),
                    ),
                  ),
                  const Spacer(),
                  const Text(
                    'Edit Date',
                    style: TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.bold,
                      fontSize: 17,
                    ),
                  ),
                  const Spacer(),
                  CupertinoButton(
                    padding: EdgeInsets.zero,
                    onPressed: () => Navigator.of(ctx).pop(selectedDate),
                    child: const Text(
                      'Done',
                      style: TextStyle(
                        color: Color.fromARGB(255, 32, 95, 255),
                        fontSize: 16,
                      ),
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 20),
            // 提示文本
            const Padding(
              padding: EdgeInsets.symmetric(horizontal: 16),
              child: Text(
                'SELECT CUSTOM DATE',
                style: TextStyle(
                  color: Colors.white54,
                  fontSize: 13,
                  letterSpacing: 1,
                ),
              ),
            ),
            const SizedBox(height: 16),
            // 核心iOS日期选择器
            SizedBox(
              height: 200, // 固定高度符合iOS设计规范
              child: CupertinoDatePicker(
                initialDateTime: defaultInitialDate,
                minimumDate: defaultFirstDate,
                maximumDate: defaultLastDate,
                mode: CupertinoDatePickerMode.date, // 仅选择日期(匹配日记App需求)
                backgroundColor: const Color.fromARGB(255, 30, 30, 30),
                onDateTimeChanged: (DateTime newDate) {
                  selectedDate = newDate;
                },
                textStyle: const TextStyle(color: Colors.white),
              ),
            ),
            const SizedBox(height: 20),
          ],
        ),
      );
    },
  );
}

关键优化点说明

  1. 无Material依赖:所有组件和样式都使用Cupertino原生组件,完全脱离Material环境限制,解决了你之前用tablecalendar的兼容性问题。
  2. 实用的返回值:函数返回Future<DateTime?>,调用者可以通过await获取用户选中的日期(Cancel则返回null),比原来的void函数更实用。
  3. 匹配日记App风格:
    • 深色背景+白色文本的深色模式设计
    • 顶部圆角的Sheet样式
    • 标准的Cancel/Done操作栏布局
  4. 灵活的参数配置:支持传入初始日期、最小/最大可选日期,适配不同场景需求。
  5. 自适应高度:使用mainAxisSize: MainAxisSize.min让Sheet高度自适应内容,符合iOS交互习惯。

如何调用这个函数

在任意Cupertino组件的交互事件中即可调用,比如:

CupertinoButton(
  onPressed: () async {
    final selectedDate = await showIOSJournalStyleDatePicker(
      context,
      initialDate: DateTime.now(), // 可选:设置默认选中日期
      firstDate: DateTime(2010), // 可选:设置最早可选日期
      lastDate: DateTime(2030), // 可选:设置最晚可选日期
    );
    if (selectedDate != null) {
      // 在这里处理用户选中的日期,比如更新页面状态
      print('用户选中的日期:$selectedDate');
    }
  },
  child: const Text('修改日期', style: TextStyle(color: Colors.white)),
)

额外提示

  • 如果你的项目是纯CupertinoApp(没有使用MaterialApp),上面的代码可以直接运行,完全兼容。
  • 如果需要调整样式(比如颜色、字体),直接修改TextStyle和Container的decoration即可,完全自定义。
  • 如果需要支持时间选择,只需把CupertinoDatePickerMode.date改成CupertinoDatePickerMode.dateAndTime即可。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 07:18:05