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

Flutter DatePicker组件改造需求:将弹窗选择转为常驻日历Widget并调整时间显示样式

Got it, let's revamp your calendar widget to show a persistent full calendar and adjust the time display to match your desired UI. Here's a complete solution with explanations:

Step 1: Add Required Dependency

First, we'll use the table_calendar package for the persistent calendar view. Add this to your pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  intl: ^0.18.1
  table_calendar: ^3.0.9 # Use the latest version available

Run flutter pub get to install it.

Step 2: Full Modified Code

Replace your existing code with this version, which includes the persistent calendar and updated time display:

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:table_calendar/table_calendar.dart';

class ExampleCalendar extends StatefulWidget {
  @override
  _ExampleCalendarState createState() => _ExampleCalendarState();
  static Route route() {
    return MaterialPageRoute<void>(builder: (_) => ExampleCalendar());
  }
}

class _ExampleCalendarState extends State<ExampleCalendar> {
  DateTime _selectedDate = DateTime.now();
  TimeOfDay _selectedTime = TimeOfDay.now();
  CalendarFormat _calendarFormat = CalendarFormat.month;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.transparent,
        leading: IconButton(
          icon: const Icon(Icons.arrow_back, color: Colors.black),
          onPressed: () => Navigator.of(context).pop(),
        ),
      ),
      body: _menuPage(context),
    );
  }

  Widget _menuPage(BuildContext context) {
    return SafeArea(
      child: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _persistentCalendarAndTimePicker(context),
          ],
        ),
      ),
    );
  }

  Widget _persistentCalendarAndTimePicker(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        children: [
          // Persistent Full Calendar
          TableCalendar(
            firstDay: DateTime.now(),
            lastDay: DateTime.now().add(const Duration(days: 100000)),
            focusedDay: _selectedDate,
            calendarFormat: _calendarFormat,
            selectedDayPredicate: (day) => isSameDay(_selectedDate, day),
            onDaySelected: (selectedDay, focusedDay) {
              setState(() => _selectedDate = selectedDay);
            },
            onFormatChanged: (format) {
              setState(() => _calendarFormat = format);
            },
            onPageChanged: (focusedDay) => _selectedDate = focusedDay,
            calendarStyle: const CalendarStyle(
              selectedDecoration: BoxDecoration(
                color: Colors.lightBlueAccent,
                shape: BoxShape.circle,
              ),
              todayDecoration: BoxDecoration(
                color: Colors.grey[300],
                shape: BoxShape.circle,
              ),
            ),
            headerStyle: const HeaderStyle(
              formatButtonVisible: true,
              titleCentered: true,
            ),
          ),
          const SizedBox(height: 20),
          // Time & Date Display Bar (matches your original layout with improvements)
          Container(
            width: double.infinity,
            height: 100,
            child: Row(
              children: [
                Expanded(
                  child: Container(
                    color: Colors.lightBlueAccent,
                    child: Center(
                      // Optional: Replace with persistent wheel picker if you don't want a dialog
                      child: TextButton(
                        onPressed: () => _openTimePicker(context),
                        child: Text(
                          _selectedTime.format(context),
                          style: const TextStyle(
                            fontSize: 30.0,
                            color: Colors.black,
                            fontWeight: FontWeight.w500,
                          ),
                        ),
                      ),
                    ),
                  ),
                ),
                Expanded(
                  child: Container(
                    color: const Color.fromRGBO(7, 190, 200, 0.1),
                    child: Center(
                      child: Text(
                        DateFormat('dd.MM.yyyy').format(_selectedDate),
                        style: const TextStyle(
                          fontSize: 28.0,
                          color: Colors.black,
                          fontWeight: FontWeight.w500,
                        ),
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Future<void> _openTimePicker(BuildContext context) async {
    final pickedTime = await showTimePicker(
      context: context,
      initialTime: _selectedTime,
      helpText: "Choose Time",
    );
    if (pickedTime != null) {
      setState(() => _selectedTime = pickedTime);
    }
  }
}

Key Changes Explained

  1. Persistent Calendar:

    • Replaced the date button with TableCalendar, which shows a full, interactive calendar directly in your UI.
    • You can switch between month/week/day views using the format button in the header.
    • Selected dates are highlighted, and tapping a date updates _selectedDate instantly.
  2. Time Display & Selection:

    • Kept your original color scheme and layout for the time/date bar, but updated the date to show full dd.MM.yyyy format (adjust this with DateFormat if you need a different style).
    • The time button still opens a picker dialog, but if you want a persistent wheel picker (no dialog), replace the TextButton with this Cupertino-style wheel:
      // Replace the TextButton in the time container with this
      Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          SizedBox(
            width: 60,
            child: CupertinoPicker(
              itemExtent: 40,
              onSelectedItemChanged: (index) {
                setState(() => _selectedTime = _selectedTime.replacing(hour: index));
              },
              children: List.generate(24, (i) => Text('${i.toString().padLeft(2, '0')}')),
            ),
          ),
          const Text(':', style: TextStyle(fontSize: 30)),
          SizedBox(
            width: 60,
            child: CupertinoPicker(
              itemExtent: 40,
              onSelectedItemChanged: (index) {
                setState(() => _selectedTime = _selectedTime.replacing(minute: index));
              },
              children: List.generate(60, (i) => Text('${i.toString().padLeft(2, '0')}')),
            ),
          ),
        ],
      )
      
    • This wheel picker stays visible in the UI, letting users adjust time without opening a dialog.
  3. State Management:

    • Split date and time into separate state variables (_selectedDate and _selectedTime) for cleaner logic.
    • All UI updates trigger setState to refresh the view immediately.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 04:07:46