Flutter时间选择器插件progressive_time_picker的使用

发布于 1周前 作者 gougou168 来自 Flutter

Flutter时间选择器插件progressive_time_picker的使用

简介

progressive_time_picker 是一个可高度自定义的时间选择器插件,适用于Flutter应用程序。它支持多个平台(Android、iOS、Web、Mac、Linux、Windows),并允许用户根据需求选择特定的时间范围。该插件提供了丰富的自定义选项,包括12小时和24小时格式的时钟数字显示、禁用特定时间范围等功能。

主要特性

  • 支持单个或同时选择两个时间点。
  • 提供了易于使用的自定义装饰选项。
  • 支持12小时和24小时格式,并且可以完全自定义。
  • 允许禁用特定的时间段以增加控制力。

预览

以下是progressive_time_picker的一些预览图:

progressive_time_picker

带有禁用时间段的时间选择器: progressive_time_picker_disabled_range progressive_time_picker_multiple_disabled_ranges

基本用法

首先,在项目中导入此包:

import 'package:progressive_time_picker/progressive_time_picker.dart';

然后以最简单的方式添加到你的界面中:

最简单的用法

TimePicker(
  initTime: PickedTime(h: 0, m: 0),
  endTime: PickedTime(h: 8, m: 0),
  onSelectionChange: (start, end, isDisableRange) =>
      print('onSelectionChange => init : ${start.h}:${start.m}, end : ${end.h}:${end.m}, isDisableRangeRange: $isDisableRange'),
  onSelectionEnd: (start, end, isDisableRange) =>
      print('onSelectionEnd => init : ${start.h}:${start.m}, end : ${end.h}:${end.m}, isDisableRangeRange: $isDisableRange'),
);

包含禁用时间段的用法

TimePicker(
  initTime: PickedTime(h: 0, m: 0),
  endTime: PickedTime(h: 8, m: 0),
  disabledRanges: [
    DisabledRange(
      initTime: PickedTime(h: 12, m: 0),
      endTime: PickedTime(h: 20, m: 0),
    ),
  ],
  disabledRangesColor: Colors.grey,
  disabledRangesErrorColor: Colors.red,
  onSelectionChange: (start, end, isDisableRange) => print(
    'onSelectionChange => init : ${start.h}:${start.m}, end : ${end.h}:${end.m}, isDisableRangeRange: $isDisableRange'),
  onSelectionEnd: (start, end, isDisableRange) => print(
    'onSelectionEnd => init : ${start.h}:${start.m}, end : ${end.h}:${end.m}, isDisableRangeRange: $isDisableRange'),
);

参数说明

TimePicker 必填参数

参数 描述
PickedTime initTime 初始选择的时间
PickedTime endTime 结束选择的时间
onSelectionChange 当初始时间和结束时间发生变化时调用的回调函数
onSelectionEnd 当初始时间和结束时间的选择完成时调用的回调函数

TimePicker 可选参数

参数 默认值 描述
double height 220 画布的高度
double width 220 画布的宽度
int primarySectors 0 要绘制的主要扇区数量
int secondarySectors 0 要绘制的次要扇区数量
Widget child Container 将放置在圆圈内部的小部件
TimePickerDecoration decoration - 用于装饰TimePicker小部件
bool isInitHandlerSelectable true 是否启用或禁用初始处理器的选择
bool isEndHandlerSelectable true 是否启用或禁用结束处理器的选择
bool isSelectableHandlerMoveAble true 是否启用或禁用未被选中的处理器移动
List<DisabledRange> null 用于禁用选择范围,如果为null,则没有禁用的时间范围
Color disabledRangesColor Colors.grey 定义禁用范围的颜色
Color disabledRangesErrorColor Colors.red 定义禁用范围错误的颜色
bool drawInitHandlerOnTop false 设置优先绘制初始处理器还是结束处理器

TimePickerDecoration 必填参数

参数 描述
TimePickerSweepDecoration sweepDecoration 用于装饰扫过部分或初始与结束点之间的区域
TimePickerHandlerDecoration initHandlerDecoration 用于装饰时间选择器的初始或结束处理器
TimePickerHandlerDecoration endHandlerDecoration 用于装饰时间选择器的初始或结束处理器

TimePickerDecoration 可选参数

参数 默认值 描述
Color baseColor cyanAccent 定义选择器的背景颜色
double pickerBaseCirclePadding 0.0 为选择器的基本或外圈添加额外的填充
TimePickerSectorDecoration primarySectorsDecoration - 用于装饰时间选择器的主要扇区
TimePickerSectorDecoration secondarySectorsDecoration - 用于装饰时间选择器的次要扇区
TimePickerClockNumberDecoration clockNumberDecoration - 提供应用于内部时钟数字的装饰选项
SystemMouseCursor mouseCursor - 用于设置PanGestureRecognizer的系统鼠标指针

示例代码

下面是一个完整的示例代码,展示了如何在应用中集成progressive_time_picker

import 'dart:developer' as dev;

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart' as intl;
import 'package:progressive_time_picker/progressive_time_picker.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]).then(
    (value) => runApp(MyApp()),
  );
  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ClockTimeFormat clockTimeFormat = ClockTimeFormat.twentyFourHours;
  ClockIncrementTimeFormat clockIncrementTimeFormat = ClockIncrementTimeFormat.fiveMin;

  PickedTime inBedTime = PickedTime(h: 0, m: 0);
  PickedTime outBedTime = PickedTime(h: 8, m: 0);
  PickedTime intervalBedTime = PickedTime(h: 0, m: 0);

  PickedTime disabledInitTime = PickedTime(h: 12, m: 0);
  PickedTime disabledEndTime = PickedTime(h: 20, m: 0);

  double sleepGoal = 8.0;
  bool isSleepGoal = false;

  bool? validRange = true;

  @override
  void initState() {
    super.initState();
    isSleepGoal = (sleepGoal >= 8.0) ? true : false;
    intervalBedTime = formatIntervalTime(
      init: inBedTime,
      end: outBedTime,
      clockTimeFormat: clockTimeFormat,
      clockIncrementTimeFormat: clockIncrementTimeFormat,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color(0xFF141925),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          Text(
            'Sleep Time',
            style: TextStyle(
              color: Color(0xFF3CDAF7),
              fontSize: 30,
              fontWeight: FontWeight.bold,
            ),
          ),
          TimePicker(
            initTime: inBedTime,
            endTime: outBedTime,
            disabledRanges: [
              DisabledRange(
                initTime: disabledInitTime,
                endTime: disabledEndTime,
              ),
            ],
            disabledRangesColor: Colors.grey,
            disabledRangesErrorColor: Colors.red,
            height: 260.0,
            width: 260.0,
            onSelectionChange: _updateLabels,
            onSelectionEnd: (start, end, isDisableRange) => dev.log(
                'onSelectionEnd => init : ${start.h}:${start.m}, end : ${end.h}:${end.m}, isDisableRange: $isDisableRange'),
            primarySectors: clockTimeFormat.value,
            secondarySectors: clockTimeFormat.value * 2,
            decoration: TimePickerDecoration(
              baseColor: Color(0xFF1F2633),
              pickerBaseCirclePadding: 15.0,
              sweepDecoration: TimePickerSweepDecoration(
                pickerStrokeWidth: 30.0,
                pickerColor: isSleepGoal ? Color(0xFF3CDAF7) : Colors.white,
                showConnector: true,
              ),
              initHandlerDecoration: TimePickerHandlerDecoration(
                color: Color(0xFF141925),
                shape: BoxShape.circle,
                radius: 12.0,
                icon: Icon(
                  Icons.power_settings_new_outlined,
                  size: 20.0,
                  color: Color(0xFF3CDAF7),
                ),
              ),
              endHandlerDecoration: TimePickerHandlerDecoration(
                color: Color(0xFF141925),
                shape: BoxShape.circle,
                radius: 12.0,
                icon: Icon(
                  Icons.notifications_active_outlined,
                  size: 20.0,
                  color: Color(0xFF3CDAF7),
                ),
              ),
              primarySectorsDecoration: TimePickerSectorDecoration(
                color: Colors.white,
                width: 1.0,
                size: 4.0,
                radiusPadding: 25.0,
              ),
              secondarySectorsDecoration: TimePickerSectorDecoration(
                color: Color(0xFF3CDAF7),
                width: 1.0,
                size: 2.0,
                radiusPadding: 25.0,
              ),
              clockNumberDecoration: TimePickerClockNumberDecoration(
                defaultTextColor: Colors.white,
                defaultFontSize: 12.0,
                scaleFactor: 2.0,
                showNumberIndicators: true,
                clockTimeFormat: clockTimeFormat,
                clockIncrementTimeFormat: clockIncrementTimeFormat,
              ),
            ),
            child: Padding(
              padding: const EdgeInsets.all(62.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    '${intl.NumberFormat('00').format(intervalBedTime.h)}Hr ${intl.NumberFormat('00').format(intervalBedTime.m)}Min',
                    style: TextStyle(
                      fontSize: 12.0,
                      color: isSleepGoal ? Color(0xFF3CDAF7) : Colors.white,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ],
              ),
            ),
          ),
          Container(
            width: 300.0,
            alignment: Alignment.center,
            decoration: BoxDecoration(
              color: Color(0xFF1F2633),
              borderRadius: BorderRadius.circular(25.0),
            ),
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Text(
                isSleepGoal
                    ? "Above Sleep Goal (>=8) 😇"
                    : 'below Sleep Goal (<=8) 😴',
                style: TextStyle(
                  color: Colors.white,
                  fontSize: 16,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              _timeWidget(
                'BedTime',
                inBedTime,
                Icon(
                  Icons.power_settings_new_outlined,
                  size: 25.0,
                  color: Color(0xFF3CDAF7),
                ),
              ),
              _timeWidget(
                'WakeUp',
                outBedTime,
                Icon(
                  Icons.notifications_active_outlined,
                  size: 25.0,
                  color: Color(0xFF3CDAF7),
                ),
              ),
            ],
          ),
          Text(
            validRange == true
                ? "Working hours ${intl.NumberFormat('00').format(disabledInitTime.h)}:${intl.NumberFormat('00').format(disabledInitTime.m)} to ${intl.NumberFormat('00').format(disabledEndTime.h)}:${intl.NumberFormat('00').format(disabledEndTime.m)}"
                : "Please schedule according working time!",
            style: TextStyle(
              fontSize: 16.0,
              color: validRange == true ? Colors.white : Colors.red,
            ),
          ),
        ],
      ),
    );
  }

  Widget _timeWidget(String title, PickedTime time, Icon icon) {
    return Container(
      width: 150.0,
      decoration: BoxDecoration(
        color: Color(0xFF1F2633),
        borderRadius: BorderRadius.circular(25.0),
      ),
      child: Padding(
        padding: const EdgeInsets.all(25.0),
        child: Column(
          children: [
            Text(
              '${intl.NumberFormat('00').format(time.h)}:${intl.NumberFormat('00').format(time.m)}',
              style: TextStyle(
                color: Color(0xFF3CDAF7),
                fontSize: 25,
                fontWeight: FontWeight.bold,
              ),
            ),
            SizedBox(height: 15),
            Text(
              title,
              style: TextStyle(
                color: Color(0xFF3CDAF7),
                fontSize: 16,
              ),
            ),
            SizedBox(height: 10),
            icon,
          ],
        ),
      ),
    );
  }

  void _updateLabels(PickedTime init, PickedTime end, bool? isDisableRange) {
    inBedTime = init;
    outBedTime = end;
    intervalBedTime = formatIntervalTime(
      init: inBedTime,
      end: outBedTime,
      clockTimeFormat: clockTimeFormat,
      clockIncrementTimeFormat: clockIncrementTimeFormat,
    );
    isSleepGoal = validateSleepGoal(
      inTime: init,
      outTime: end,
      sleepGoal: sleepGoal,
      clockTimeFormat: clockTimeFormat,
      clockIncrementTimeFormat: clockIncrementTimeFormat,
    );
    setState(() {
      validRange = isDisableRange;
    });
  }
}

以上是关于progressive_time_picker插件的详细介绍和使用方法,希望对您有所帮助!如果您有任何问题或建议,请随时联系开发者团队。


更多关于Flutter时间选择器插件progressive_time_picker的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter时间选择器插件progressive_time_picker的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用progressive_time_picker插件的示例代码。progressive_time_picker是一个允许用户选择时间的Flutter插件,它提供了一个直观且用户友好的界面。

首先,你需要在你的pubspec.yaml文件中添加该插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  progressive_time_picker: ^x.y.z  # 请将x.y.z替换为最新版本号

然后,运行flutter pub get来安装依赖。

接下来,你可以在你的Flutter应用中使用ProgressiveTimePicker。以下是一个完整的示例代码,展示了如何在一个简单的Flutter应用中集成和使用progressive_time_picker

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  DateTime? selectedTime;

  void _selectTime() async {
    final DateTime? picked = await showProgressiveTimePicker(
      context: context,
      locale: Localizations.localeOf(context),
      initialTime: selectedTime ?? DateTime.now(),
      theme: ProgressivePickerThemeData.lightTheme(), // 可以选择使用lightTheme()或darkTheme()
    );

    if (picked != null && picked != selectedTime) {
      setState(() {
        selectedTime = picked;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Progressive Time Picker Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              selectedTime == null
                  ? 'No time selected'
                  : 'Selected Time: ${selectedTime!.toLocal()}',
              style: TextStyle(fontSize: 24),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _selectTime,
              child: Text('Select Time'),
            ),
          ],
        ),
      ),
    );
  }
}

解释

  1. 依赖添加

    • pubspec.yaml中添加progressive_time_picker的依赖。
  2. 导入包

    • 在你的Dart文件中导入progressive_time_picker包。
  3. 创建UI

    • 使用Scaffold来创建一个简单的页面布局。
    • 使用Text来显示当前选择的时间(如果没有选择时间,则显示"No time selected")。
    • 使用ElevatedButton来触发时间选择器。
  4. 选择时间

    • 使用showProgressiveTimePicker方法来显示时间选择器。
    • 当用户选择时间后,更新selectedTime状态。
  5. 样式和主题

    • ProgressivePickerThemeData.lightTheme()ProgressivePickerThemeData.darkTheme() 可以用来设置时间选择器的主题。

这个示例展示了如何在Flutter应用中集成和使用progressive_time_picker插件。你可以根据需要进行进一步的自定义和扩展。

回到顶部