custom_time_picker 0.0.2 copy "custom_time_picker: ^0.0.2" to clipboard
custom_time_picker: ^0.0.2 copied to clipboard

Extended Material Design time picker with onChange and onConfirm callbacks, custom child widget support, and full theme customization.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:custom_time_picker/custom_time_picker.dart' as custom;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Custom Time Picker Example',
      debugShowCheckedModeBanner: false,
      theme: ThemeData.dark(useMaterial3: true).copyWith(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.deepPurple,
          brightness: Brightness.dark,
        ),
        scaffoldBackgroundColor: const Color(0xFF1A1A1A),
        cardTheme: CardTheme(
          color: const Color(0xFF2D2D2D),
          elevation: 4,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16),
          ),
        ),
      ),
      home: const TimePickerExample(),
    );
  }
}

class TimePickerExample extends StatefulWidget {
  const TimePickerExample({super.key});

  @override
  State<TimePickerExample> createState() => _TimePickerExampleState();
}

class _TimePickerExampleState extends State<TimePickerExample> {
  TimeOfDay? selectedTime;
  TimeOfDay? currentChangingTime;
  final List<String> logs = [];

  void _addLog(String message) {
    setState(() {
      logs.insert(0, '${TimeOfDay.now().format(context)} - $message');
      if (logs.length > 10) {
        logs.removeLast();
      }
    });
  }

  Future<void> _showTimePicker() async {
    final TimeOfDay? picked = await custom.showTimePicker(
      context: context,
      initialTime: selectedTime ?? TimeOfDay.now(),
      onChange: (TimeOfDay time) {
        setState(() {
          currentChangingTime = time;
        });
        _addLog('onChange: ${time.format(context)}');
      },
      onConfirm: (TimeOfDay time) {
        _addLog('onConfirm: ${time.format(context)}');
      },
      builder: (BuildContext context, Widget? child) {
        return MediaQuery(
          data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true),
          child: Theme(
            data: Theme.of(context).copyWith(
              timePickerTheme: TimePickerThemeData(
                backgroundColor: const Color(0xFF2D2D2D),
                hourMinuteShape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(12),
                  side: BorderSide(
                    color: Colors.deepPurple.withValues(alpha: 0.3),
                    width: 2,
                  ),
                ),
                dayPeriodShape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(12),
                ),
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(20),
                ),
              ),
            ),
            child: child!,
          ),
        );
      },
    );

    if (!mounted) return;

    if (picked != null) {
      setState(() {
        selectedTime = picked;
        currentChangingTime = null;
      });
      _addLog('Time selected: ${picked.format(context)}');
    } else {
      setState(() {
        currentChangingTime = null;
      });
      _addLog('Time picker cancelled');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Custom Time Picker Example'),
        centerTitle: true,
        backgroundColor: const Color(0xFF2D2D2D),
        elevation: 0,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Card(
              child: Padding(
                padding: const EdgeInsets.all(24),
                child: Column(
                  children: [
                    Icon(
                      Icons.access_time,
                      size: 64,
                      color: Colors.deepPurple.shade300,
                    ),
                    const SizedBox(height: 16),
                    const Text(
                      'Selected Time',
                      style: TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.w500,
                        color: Colors.white70,
                      ),
                    ),
                    const SizedBox(height: 8),
                    Text(
                      selectedTime?.format(context) ?? 'Not selected',
                      style: TextStyle(
                        fontSize: 48,
                        fontWeight: FontWeight.bold,
                        color: selectedTime != null ? Colors.deepPurple.shade200 : Colors.white30,
                      ),
                    ),
                    if (currentChangingTime != null) ...[
                      const SizedBox(height: 16),
                      Container(
                        padding: const EdgeInsets.symmetric(
                          horizontal: 16,
                          vertical: 8,
                        ),
                        decoration: BoxDecoration(
                          color: Colors.deepPurple.withValues(alpha: 0.2),
                          borderRadius: BorderRadius.circular(8),
                        ),
                        child: Text(
                          'Changing: ${currentChangingTime!.format(context)}',
                          style: TextStyle(
                            fontSize: 16,
                            color: Colors.deepPurple.shade200,
                            fontWeight: FontWeight.w500,
                          ),
                        ),
                      ),
                    ],
                    const SizedBox(height: 24),
                    ElevatedButton.icon(
                      onPressed: _showTimePicker,
                      icon: const Icon(Icons.schedule),
                      label: const Text('Pick Time'),
                      style: ElevatedButton.styleFrom(
                        backgroundColor: Colors.deepPurple,
                        foregroundColor: Colors.white,
                        padding: const EdgeInsets.symmetric(
                          horizontal: 32,
                          vertical: 16,
                        ),
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(12),
                        ),
                        elevation: 4,
                      ),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 24),
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      children: [
                        Icon(
                          Icons.history,
                          color: Colors.deepPurple.shade300,
                        ),
                        const SizedBox(width: 8),
                        const Text(
                          'Callback Logs',
                          style: TextStyle(
                            fontSize: 18,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      ],
                    ),
                    const SizedBox(height: 16),
                    if (logs.isEmpty)
                      const Padding(
                        padding: EdgeInsets.all(16),
                        child: Center(
                          child: Text(
                            'No logs yet. Pick a time to see callbacks!',
                            style: TextStyle(
                              color: Colors.white38,
                              fontStyle: FontStyle.italic,
                            ),
                          ),
                        ),
                      )
                    else
                      ...logs.map((log) => Padding(
                            padding: const EdgeInsets.only(bottom: 8),
                            child: Container(
                              padding: const EdgeInsets.all(12),
                              decoration: BoxDecoration(
                                color: const Color(0xFF1A1A1A),
                                borderRadius: BorderRadius.circular(8),
                                border: Border.all(
                                  color: Colors.deepPurple.withValues(alpha: 0.2),
                                ),
                              ),
                              child: Row(
                                children: [
                                  Icon(
                                    Icons.chevron_right,
                                    size: 16,
                                    color: Colors.deepPurple.shade300,
                                  ),
                                  const SizedBox(width: 8),
                                  Expanded(
                                    child: Text(
                                      log,
                                      style: const TextStyle(
                                        fontFamily: 'monospace',
                                        fontSize: 13,
                                        color: Colors.white70,
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          )),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 24),
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      children: [
                        Icon(
                          Icons.info_outline,
                          color: Colors.deepPurple.shade300,
                        ),
                        const SizedBox(width: 8),
                        const Text(
                          'Features',
                          style: TextStyle(
                            fontSize: 18,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      ],
                    ),
                    const SizedBox(height: 16),
                    _buildFeatureItem(
                      'onChange callback',
                      'Called every time the user changes hours or minutes',
                    ),
                    _buildFeatureItem(
                      'onConfirm callback',
                      'Called when the user confirms the time selection',
                    ),
                    _buildFeatureItem(
                      'Dark theme',
                      'Beautiful dark theme customization',
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildFeatureItem(String title, String description) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 12),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Icon(
            Icons.check_circle,
            color: Colors.deepPurple.shade300,
            size: 20,
          ),
          const SizedBox(width: 12),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  title,
                  style: const TextStyle(
                    fontWeight: FontWeight.w600,
                    fontSize: 14,
                  ),
                ),
                const SizedBox(height: 4),
                Text(
                  description,
                  style: const TextStyle(
                    fontSize: 12,
                    color: Colors.white60,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
1
likes
90
points
123
downloads

Publisher

unverified uploader

Weekly Downloads

Extended Material Design time picker with onChange and onConfirm callbacks, custom child widget support, and full theme customization.

Repository (GitHub)
View/report issues

Topics

#timepicker #material-design #flutter-widget #ui

Documentation

API reference

License

BSD-3-Clause (license)

Dependencies

flutter

More

Packages that depend on custom_time_picker