Flutter波斯语日期时间选择器插件persian_datetime_picker的使用

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

Flutter波斯语日期时间选择器插件persian_datetime_picker的使用

简介

Persian DateTime Picker Banner

persian_datetime_picker 是一个为Flutter设计的波斯(Farsi, Shamsi, Jalali)日期和时间选择器,灵感来源于Material Design的DateTime picker,并基于shamsi_date库构建。它完全支持波斯(Jalali)日历,并且具有高度可定制性,包括与Material 3的兼容性。

此外,它还支持多种语言,如波斯语、达里语、库尔德语、普什图语以及自定义区域设置,同时确保与Flutter的无缝集成并遵循Material Design标准。

功能特性

  • 🌟 完全支持波斯(Jalali)日历
  • 🛠 高度可定制
  • 💻 支持Material 3
  • 🌎 多语言支持:波斯语、达里语、库尔德语、普什图语及自定义区域设置
  • 📱 符合Material Design标准

开始使用

要使用persian_datetime_picker,请先在您的pubspec.yaml文件中添加该包:

dependencies:
  persian_datetime_picker: <latest_version>

然后,在Dart代码中导入它:

import 'package:persian_datetime_picker/persian_datetime_picker.dart';

接下来,为MaterialApp添加本地化支持:

return MaterialApp(
  title: 'Date and Time Pickers',
  locale: const Locale("fa", "IR"),
  supportedLocales: const [
    Locale("fa", "IR"),
    Locale("en", "US"),
  ],
  localizationsDelegates: const [
    PersianMaterialLocalizations.delegate,
    PersianCupertinoLocalizations.delegate,
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  // ...
);

使用示例

1. 波斯日期选择器

Persian Date Picker

Jalali? picked = await showPersianDatePicker(
  context: context,
  initialDate: Jalali.now(),
  firstDate: Jalali(1385, 8),
  lastDate: Jalali(1450, 9),
  initialEntryMode: PersianDatePickerEntryMode.calendarOnly,
  initialDatePickerMode: PersianDatePickerMode.year,
);
var label = picked.formatFullDate();

2. 波斯时间选择器

Persian Time Picker Persian Input Time Picker

var picked = await showTimePicker(
  context: context,
  initialTime: TimeOfDay.now(),
  initialEntryMode: TimePickerEntryMode.input,
  builder: (BuildContext context, Widget? child) {
    return Directionality(
      textDirection: TextDirection.rtl,
      child: MediaQuery(
        data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true),
        child: child!,
      ),
    );
  },
);
if (picked != null) String label = picked.toString();

3. 模态底部弹出框与波斯Cupertino日期选择器

Persian Cupertino Date Picker

Jalali? pickedDate = await showModalBottomSheet<Jalali>(
  context: context,
  builder: (context) {
    Jalali? tempPickedDate;
    return Container(
      height: 250,
      child: Column(
        children: <Widget>[
          Container(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                CupertinoButton(
                  child: Text(
                    'لغو',
                    style: TextStyle(fontFamily: 'Dana'),
                  ),
                  onPressed: () => Navigator.of(context).pop(),
                ),
                CupertinoButton(
                  child: Text(
                    'تایید',
                    style: TextStyle(fontFamily: 'Dana'),
                  ),
                  onPressed: () => Navigator.of(context).pop(tempPickedDate ?? Jalali.now()),
                ),
              ],
            ),
          ),
          Divider(height: 0, thickness: 1,),
          Expanded(
            child: Container(
              child: PersianCupertinoDatePicker(
                initialDateTime: Jalali.now(),
                mode: PersianCupertinoDatePickerMode.time,
                onDateTimeChanged: (Jalali dateTime) => tempPickedDate = dateTime,
              ),
            ),
          ),
        ],
      ),
    );
  },
);

if (pickedDate != null) {
   String label = '${pickedDate.toJalaliDateTime()}';
}

4. 波斯日期范围选择器

Persian Date Range Picker Persian Input Range Picker

var picked = await showPersianDateRangePicker(
  context: context,
  initialDateRange: JalaliRange(start: Jalali(1400, 1, 2), end: Jalali(1400, 1, 10)),
  firstDate: Jalali(1385, 8),
  lastDate: Jalali(1450, 9),
  initialDate: Jalali.now(),
);
String label = "${picked?.start?.toJalaliDateTime() ?? ""} ${picked?.end?.toJalaliDateTime() ?? ""}";

5. 自定义日期选择器样式

可以通过修改ThemeData中的DatePickerTheme来自定义PersianDateTimePickerPersianCupertinoDatePicker的样式。

示例:为PersianDatePick应用主题

return MaterialApp(
  theme: ThemeData(
    datePickerTheme: DatePickerThemeData(
      backgroundColor: Colors.white,
      primaryColor: Colors.teal,
      textColor: Colors.black,
    ),
  ),
  // ...
);

在Builder中自定义PersianDatePicker

Jalali? picked = await showPersianDatePicker(
  context: context,
  initialDate: Jalali.now(),
  firstDate: Jalali(1385, 8),
  lastDate: Jalali(1450, 9),
  builder: (context, child) {
    return Theme(
      data: Theme.of(context).copyWith(
        primaryColor: Colors.teal,
        accentColor: Colors.amber,
      ),
      child: child!,
    );
  },
);

自定义PersianCupertinoDatePicker样式

showCupertinoModalPopup(
  context: context,
  builder: (context) {
    return CupertinoTheme(
      data: CupertinoThemeData(
        textTheme: CupertinoTextThemeData(
          dateTimePickerTextStyle: TextStyle(color: Colors.white),
        ),
      ),
      child: Container(
        height: 300,
        child: PersianCupertinoDatePicker(
          mode: PersianCupertinoDatePickerMode.dateAndTime,
          onDateTimeChanged: (Jalali dateTime) {
            // Handle date change
          },
        ),
      ),
    );
  },
);

6. 使用Material 2而非Material 3

如果希望使用Material 2而不是Material 3,则可以在MaterialApp中将useMaterial3参数设置为false

return MaterialApp(
  title: 'Persian DateTime Picker',
  theme: ThemeData(
    useMaterial3: false,
    datePickerTheme: DatePickerThemeData(
      backgroundColor: Colors.white,
      primaryColor: Colors.teal,
      textColor: Colors.black,
    ),
  ),
  home: MyHomePage(),
);

完整示例Demo

下面是一个完整的示例应用程序,展示了如何使用persian_datetime_picker来创建一个包含多个日期和时间选择器的界面。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Date and Time Pickers',
      locale: const Locale("fa", "IR"),
      debugShowCheckedModeBanner: false,
      supportedLocales: const [
        Locale("fa", "IR"),
        Locale("en", "US"),
      ],
      localizationsDelegates: const [
        PersianMaterialLocalizations.delegate,
        PersianCupertinoLocalizations.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      theme: ThemeData(
        fontFamily: 'Dana',
        datePickerTheme: DatePickerThemeData(
          // Customize styles here...
        ),
      ),
      home: const HomePage(),
    );
  }
}

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

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  String label = '';
  String selectedDate = Jalali.now().toJalaliDateTime();

  @override
  void initState() {
    super.initState();
    label = 'انتخاب تاریخ زمان';
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: const Text(
          'دیت تایم پیکر فارسی',
          textAlign: TextAlign.center,
          style: TextStyle(color: Colors.black),
        ),
        centerTitle: true,
        backgroundColor: Colors.transparent,
        elevation: 0,
      ),
      body: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topCenter,
            colors: [Colors.white, Color(0xffE4F5F9)],
          ),
        ),
        child: SingleChildScrollView(
          padding: EdgeInsets.symmetric(horizontal: 10),
          physics: BouncingScrollPhysics(),
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Expanded(
                child: Column(
                  children: [
                    imageButton(
                      onTap: () async {
                        Jalali? picked = await showPersianDatePicker(
                          context: context,
                          initialDate: Jalali.now(),
                          firstDate: Jalali(1385, 8),
                          lastDate: Jalali(1450, 9),
                          initialEntryMode: PersianDatePickerEntryMode.calendarOnly,
                          initialDatePickerMode: PersianDatePickerMode.year,
                        );
                        if (picked != null && picked != selectedDate) {
                          setState(() {
                            label = picked.toJalaliDateTime();
                          });
                        }
                      },
                      image: '08',
                    ),
                    imageButton(
                      onTap: () async {
                        Jalali? pickedDate = await showModalBottomSheet<Jalali>(
                          context: context,
                          builder: (context) {
                            Jalali? tempPickedDate;
                            return Container(
                              height: 250,
                              child: Column(
                                children: <Widget>[
                                  Container(
                                    child: Row(
                                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                      children: <Widget>[
                                        CupertinoButton(
                                          child: Text(
                                            'لغو',
                                            style: TextStyle(fontFamily: 'Dana'),
                                          ),
                                          onPressed: () => Navigator.of(context).pop(),
                                        ),
                                        CupertinoButton(
                                          child: Text(
                                            'تایید',
                                            style: TextStyle(fontFamily: 'Dana'),
                                          ),
                                          onPressed: () => Navigator.of(context).pop(tempPickedDate ?? Jalali.now()),
                                        ),
                                      ],
                                    ),
                                  ),
                                  Divider(height: 0, thickness: 1,),
                                  Expanded(
                                    child: Container(
                                      child: CupertinoTheme(
                                        data: CupertinoThemeData(
                                          textTheme: CupertinoTextThemeData(
                                            textStyle: TextStyle(fontFamily: 'Dana'),
                                            dateTimePickerTextStyle: TextStyle(fontFamily: 'Dana', fontSize: 20),
                                          ),
                                        ),
                                        child: PersianCupertinoDatePicker(
                                          mode: PersianCupertinoDatePickerMode.date,
                                          dateOrder: DatePickerDateOrder.dmy,
                                          onDateTimeChanged: (Jalali dateTime) => tempPickedDate = dateTime,
                                        ),
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            );
                          },
                        );

                        if (pickedDate != null) {
                          setState(() {
                            label = '${pickedDate.toDateTime()}';
                          });
                        }
                      },
                      image: '07',
                    ),
                    imageButton(
                      onTap: () async {
                        var picked = await showTimePicker(
                          context: context,
                          initialTime: TimeOfDay.now(),
                          initialEntryMode: TimePickerEntryMode.input,
                          builder: (BuildContext context, Widget? child) {
                            return Directionality(
                              textDirection: TextDirection.rtl,
                              child: MediaQuery(
                                data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true),
                                child: child!,
                              ),
                            );
                          },
                        );
                        setState(() {
                          if (picked != null) label = picked.toString();
                        });
                      },
                      image: '09',
                    ),
                    imageButton(
                      onTap: () async {
                        Jalali? pickedDate = await showModalBottomSheet<Jalali>(
                          context: context,
                          builder: (context) {
                            Jalali? tempPickedDate;
                            return Container(
                              height: 250,
                              child: Column(
                                children: <Widget>[
                                  Container(
                                    child: Row(
                                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                      children: <Widget>[
                                        CupertinoButton(
                                          child: Text(
                                            'لغو',
                                            style: TextStyle(fontFamily: 'Dana'),
                                          ),
                                          onPressed: () => Navigator.of(context).pop(),
                                        ),
                                        CupertinoButton(
                                          child: Text(
                                            'تایید',
                                            style: TextStyle(fontFamily: 'Dana'),
                                          ),
                                          onPressed: () => Navigator.of(context).pop(tempPickedDate ?? Jalali.now()),
                                        ),
                                      ],
                                    ),
                                  ),
                                  Divider(height: 0, thickness: 1,),
                                  Expanded(
                                    child: Container(
                                      child: PersianCupertinoDatePicker(
                                        initialDateTime: Jalali.now(),
                                        mode: PersianCupertinoDatePickerMode.time,
                                        onDateTimeChanged: (Jalali dateTime) => tempPickedDate = dateTime,
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            );
                          },
                        );

                        if (pickedDate != null) {
                          setState(() {
                            label = '${pickedDate.toJalaliDateTime()}';
                          });
                        }
                      },
                      image: '05',
                    ),
                  ],
                ),
              ),
              Expanded(
                child: Column(
                  children: [
                    imageButton(
                      onTap: () async {
                        var picked = await showPersianDateRangePicker(
                          context: context,
                          initialDateRange: JalaliRange(start: Jalali(1400, 1, 2), end: Jalali(1400, 1, 10)),
                          firstDate: Jalali(1385, 8),
                          lastDate: Jalali(1450, 9),
                          initialDate: Jalali.now(),
                        );
                        setState(() {
                          label = "${picked?.start?.toJalaliDateTime() ?? ""} ${picked?.end?.toJalaliDateTime() ?? ""}";
                        });
                      },
                      image: '03',
                    ),
                    imageButton(
                      onTap: () async {
                        var picked = await showPersianDateRangePicker(
                          context: context,
                          initialEntryMode: PersianDatePickerEntryMode.input,
                          initialDateRange: JalaliRange(start: Jalali(1400, 1, 2), end: Jalali(1400, 1, 10)),
                          firstDate: Jalali(1385, 8),
                          lastDate: Jalali(1450, 9),
                          initialDate: Jalali.now(),
                        );
                        setState(() {
                          label = "${picked?.start?.toJalaliDateTime() ?? ""} ${picked?.end?.toJalaliDateTime() ?? ""}";
                        });
                      },
                      image: '06',
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
      bottomNavigationBar: Container(
        height: 70,
        width: double.infinity,
        padding: EdgeInsets.all(10),
        decoration: BoxDecoration(
          boxShadow: [
            BoxShadow(
              blurRadius: 3,
              spreadRadius: 0,
              offset: Offset(0, 4),
              color: Color(0xff000000).withOpacity(0.3),
            ),
          ],
          color: Colors.white,
        ),
        child: Center(
          child: Text(
            label,
            style: Theme.of(context).textTheme.headlineSmall!.copyWith(color: Colors.black),
            textAlign: TextAlign.center,
          ),
        ),
      ),
    );
  }

  Widget imageButton({
    required Function onTap,
    required String image,
  }) {
    return ScaleGesture(
      onTap: onTap,
      child: Container(
        margin: EdgeInsets.all(10),
        decoration: BoxDecoration(
          color: Colors.white,
          boxShadow: [
            BoxShadow(
              blurRadius: 3,
              spreadRadius: 0,
              offset: Offset(0, 4),
              color: Color(0xff000000).withOpacity(0.3),
            ),
          ],
          borderRadius: BorderRadius.all(Radius.circular(10)),
        ),
        child: Image.asset(
          'assets/images/$image.png',
          fit: BoxFit.fitWidth,
        ),
      ),
    );
  }
}

class ScaleGesture extends StatefulWidget {
  final Widget child;
  final double scale;
  final Function onTap;

  ScaleGesture({
    required this.child,
    this.scale = 1.1,
    required this.onTap,
  });

  @override
  _ScaleGestureState createState() => _ScaleGestureState();
}

class _ScaleGestureState extends State<ScaleGesture> {
  late double scale;

  @override
  void initState() {
    scale = 1;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (detail) {
        setState(() {
          scale = widget.scale;
        });
      },
      onTapCancel: () {
        setState(() {
          scale = 1;
        });
      },
      onTapUp: (detail) {
        setState(() {
          scale = 1;
        });
        widget.onTap();
      },
      child: Transform.scale(
        scale: scale,
        child: widget.child,
      ),
    );
  }
}

通过上述步骤和示例代码,您可以轻松地在Flutter项目中集成并使用persian_datetime_picker插件,以实现符合波斯日历标准的日期和时间选择功能。


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

1 回复

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


当然,以下是如何在Flutter应用中使用persian_datetime_picker插件来选择波斯语日期和时间的示例代码。这个插件允许你以波斯语(也称为波斯文或法尔西语)显示日期和时间选择器。

首先,确保你已经在pubspec.yaml文件中添加了persian_datetime_picker依赖:

dependencies:
  flutter:
    sdk: flutter
  persian_datetime_picker: ^latest_version  # 请替换为最新版本号

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

接下来,你可以在你的Dart文件中使用PersianDatePickerPersianTimePicker。以下是一个完整的示例,展示了如何使用这些组件:

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

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

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

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Persian DateTime Picker Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Selected Date: ${selectedDate != null ? selectedDate!.toLocal().toString() : 'None'}',
              style: TextStyle(fontSize: 18),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                final DateTime? pickedDate = await showPersianDatePicker(
                  context: context,
                  initialDate: selectedDate ?? DateTime.now(),
                  firstDate: DateTime(1900),
                  lastDate: DateTime(2101),
                );
                if (pickedDate != null && pickedDate != selectedDate) {
                  setState(() {
                    selectedDate = pickedDate;
                  });
                }
              },
              child: Text('Select Date'),
            ),
            SizedBox(height: 30),
            Text(
              'Selected Time: ${selectedTime != null ? selectedTime!.format(context) : 'None'}',
              style: TextStyle(fontSize: 18),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () async {
                final TimeOfDay? pickedTime = await showPersianTimePicker(
                  context: context,
                  initialTime: selectedTime ?? TimeOfDay.now(),
                );
                if (pickedTime != null && pickedTime != selectedTime) {
                  setState(() {
                    selectedTime = pickedTime;
                  });
                }
              },
              child: Text('Select Time'),
            ),
          ],
        ),
      ),
    );
  }
}

在这个示例中:

  1. 我们创建了一个简单的Flutter应用,包含一个主屏幕(MyHomePage)。
  2. 主屏幕上有两个按钮,一个用于选择日期,另一个用于选择时间。
  3. 使用showPersianDatePicker函数显示波斯语日期选择器,用户选择日期后,将更新selectedDate状态。
  4. 使用showPersianTimePicker函数显示波斯语时间选择器,用户选择时间后,将更新selectedTime状态。

确保你的应用已正确安装并运行persian_datetime_picker插件,然后你可以通过点击按钮来选择日期和时间,这些选择将以波斯语格式显示。

回到顶部