flutter 手写日历组件

这篇具有很好参考价值的文章主要介绍了flutter 手写日历组件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

先看效果

flutter 手写日历组件,flutter,前端

 直接上代码

calendar_popup_view.dart

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

import 'custom_calendar.dart';
import 'hotel_app_theme.dart';

class CalendarPopupView extends StatefulWidget {
  const CalendarPopupView({
    required this.initialStartDate,
    required this.initialEndDate,
    required this.onApplyClick,
    required this.onCancelClick,
    required this.state,
    this.minimumDate,
    this.maximumDate,
    this.barrierDismissible = true,
    super.key,
  });

  final DateTime? minimumDate;
  final DateTime? maximumDate;
  final bool barrierDismissible;
  final DateTime initialStartDate;
  final DateTime initialEndDate;
  final Function(DateTime, DateTime) onApplyClick;

  final Function onCancelClick;
  final Function state;
  @override
  State<CalendarPopupView> createState() => _CalendarPopupViewState();
}

class _CalendarPopupViewState extends State<CalendarPopupView>
    with TickerProviderStateMixin {
  late DateTime startDate;
  late DateTime endDate;
  late final AnimationController animationController;
  late DateTime curSelectStartData;
  late DateTime curSelectEndData;
  @override
  void initState() {
    super.initState();
    animationController = AnimationController(
        duration: const Duration(milliseconds: 400), vsync: this);
    startDate = widget.initialStartDate;
    endDate = widget.initialEndDate;
    curSelectStartData = startDate;
    curSelectEndData = endDate;
    animationController.forward();
  }

  @override
  void dispose() {
    animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: animationController,
      builder: (BuildContext context, _) {
        return AnimatedOpacity(
          duration: const Duration(milliseconds: 100),
          opacity: animationController.value,
          child: InkWell(
            splashColor: Colors.transparent,
            focusColor: Colors.transparent,
            highlightColor: Colors.transparent,
            hoverColor: Colors.transparent,
            onTap: () {
              if (widget.barrierDismissible) {
                Navigator.pop(context);
              }
            },
            child: Container(
              decoration: BoxDecoration(
                color: HotelAppTheme.buildLightTheme().colorScheme.background,
                borderRadius: const BorderRadius.all(Radius.circular(24.0)),
                boxShadow: <BoxShadow>[
                  BoxShadow(
                      color: Colors.grey.withOpacity(0.2),
                      offset: const Offset(4, 4),
                      blurRadius: 8.0),
                ],
              ),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  Row(
                    children: <Widget>[
                      Expanded(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            Text(
                              'From',
                              textAlign: TextAlign.left,
                              style: grayTitle(),
                            ),
                            const SizedBox(
                              height: 4,
                            ),
                            Text(
                              DateFormat('EEE, dd MMM')
                                  .format(curSelectStartData),
                              style:
                                  curSelectStartData == widget.initialStartDate
                                      ? grayTime()
                                      : primaryTime(),
                            ),
                          ],
                        ),
                      ),
                      Container(
                        height: 74,
                        width: 1,
                        color: HotelAppTheme.buildLightTheme().dividerColor,
                      ),
                      Expanded(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            Text(
                              'To',
                              style: grayTitle(),
                            ),
                            const SizedBox(height: 4),
                            Text(
                              DateFormat('EEE, dd MMM')
                                  .format(curSelectEndData),
                              style: curSelectEndData == widget.initialEndDate
                                  ? grayTime()
                                  : primaryTime(),
                            ),
                          ],
                        ),
                      )
                    ],
                  ),
                  const Divider(height: 1),
                  CustomCalendarView(
                      minimumDate: widget.minimumDate,
                      maximumDate: widget.maximumDate,
                      initialEndDate: widget.initialEndDate,
                      initialStartDate: widget.initialStartDate,
                      startEndDateChange:
                          (DateTime startDateData, DateTime endDateData) {
                        if (mounted) {
                          setState(() {
                            startDate = startDateData;
                            endDate = endDateData;
                            curSelectStartData = startDateData;
                            curSelectEndData = endDateData;
                          });
                          toUpdateState();
                        }
                      },
                      endDateChange: (DateTime endData) {
                        print("endDateChange");
                        setState(() {
                          endDate = endData;
                          curSelectEndData = endData;
                        });
                        toUpdateState();
                      },
                      startDateChange: (DateTime startData) {
                        print("startDateChange");
                        setState(() {
                          startDate = startData;
                          curSelectStartData = startData;
                        });
                        toUpdateState();
                      }),
                  Padding(
                    padding: const EdgeInsets.only(
                        left: 16, right: 16, bottom: 16, top: 8),
                    child: Container(
                      height: 48,
                      decoration: BoxDecoration(
                        color: HotelAppTheme.buildLightTheme().primaryColor,
                        borderRadius:
                            const BorderRadius.all(Radius.circular(24.0)),
                        boxShadow: <BoxShadow>[
                          BoxShadow(
                            color: Colors.grey.withOpacity(0.6),
                            blurRadius: 8,
                            offset: const Offset(4, 4),
                          ),
                        ],
                      ),
                      child: Material(
                        color: Colors.transparent,
                        child: InkWell(
                          borderRadius:
                              const BorderRadius.all(Radius.circular(24.0)),
                          highlightColor: Colors.transparent,
                          onTap: () {
                            try {
                              // animationController?.reverse().then((f) {

                              // });
                              widget.onApplyClick(startDate, endDate);
                              Navigator.pop(context);
                            } catch (_) {}
                          },
                          child: const Center(
                            child: Text(
                              'Apply',
                              style: TextStyle(
                                  fontWeight: FontWeight.w500,
                                  fontSize: 18,
                                  color: Colors.white),
                            ),
                          ),
                        ),
                      ),
                    ),
                  )
                ],
              ),
            ),
          ),
        );
      },
    );
  }

  toUpdateState() {
    widget.state(() {});
  }

  TextStyle grayTitle() {
    return const TextStyle(
      fontWeight: FontWeight.w100,
      fontSize: 16,
      color: Color(0xff676970),
    );
  }

  TextStyle grayTime() {
    return const TextStyle(
      fontWeight: FontWeight.bold,
      fontSize: 16,
      color: Color(0xff45474D),
    );
  }

  TextStyle primaryTime() {
    return TextStyle(
      fontWeight: FontWeight.bold,
      fontSize: 16,
      color: HotelAppTheme.buildLightTheme().primaryColorDark,
    );
  }
}

custom_calendar.dart

import 'package:app/common/util/k_date_util.dart';
import 'package:app/common/util/k_log_util.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:intl/intl.dart';

import 'hotel_app_theme.dart';

class CustomCalendarView extends StatefulWidget {
  const CustomCalendarView({
    required this.initialStartDate,
    required this.initialEndDate,
    required this.startEndDateChange,
    required this.startDateChange,
    required this.endDateChange,
    this.minimumDate,
    this.maximumDate,
    super.key,
  });

  final DateTime? minimumDate;
  final DateTime? maximumDate;
  final DateTime initialStartDate;
  final DateTime initialEndDate;

  final Function(DateTime, DateTime) startEndDateChange;
  final Function(DateTime) startDateChange;
  final Function(DateTime) endDateChange;
  @override
  State<CustomCalendarView> createState() => _CustomCalendarViewState();
}

class _CustomCalendarViewState extends State<CustomCalendarView> {
  List<DateTime> dateList = <DateTime>[];
  DateTime currentMonthDate = DateTime.now();
  DateTime? startDate;
  DateTime? endDate;

  @override
  void initState() {
    super.initState();
    setListOfDate(currentMonthDate);
    startDate = widget.initialStartDate;
    endDate = widget.initialEndDate;
  }

  @override
  void dispose() {
    super.dispose();
  }

  void setListOfDate(DateTime monthDate) {
    dateList.clear();
    final DateTime newDate = DateTime(monthDate.year, monthDate.month, 0);
    int previousMothDay = 0;
    if (newDate.weekday < 7) {
      previousMothDay = newDate.weekday;
      for (int i = 1; i <= previousMothDay; i++) {
        dateList.add(newDate.subtract(Duration(days: previousMothDay - i)));
      }
    }
    for (int i = 0; i < (42 - previousMothDay); i++) {
      dateList.add(newDate.add(Duration(days: i + 1)));
    }
    // if (dateList[dateList.length - 7].month != monthDate.month) {
    //   dateList.removeRange(dateList.length - 7, dateList.length);
    // }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: <Widget>[
          Padding(
            padding:
                const EdgeInsets.only(left: 8.0, right: 8.0, top: 4, bottom: 4),
            child: Row(
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Container(
                    height: 38,
                    width: 38,
                    decoration: BoxDecoration(
                      borderRadius:
                          const BorderRadius.all(Radius.circular(24.0)),
                      border: Border.all(
                        color: HotelAppTheme.buildLightTheme().dividerColor,
                      ),
                    ),
                    child: InkWell(
                      borderRadius:
                          const BorderRadius.all(Radius.circular(24.0)),
                      onTap: () {
                        if (mounted) {
                          setState(() {
                            if (getCurMonthIsInMinMaxRange(DateTime(
                                currentMonthDate.year,
                                currentMonthDate.month,
                                0))) {
                              currentMonthDate = DateTime(currentMonthDate.year,
                                  currentMonthDate.month, 0);
                              setListOfDate(currentMonthDate);
                            }
                          });
                        }
                      },
                      child: const Icon(
                        Icons.keyboard_arrow_left,
                        color: Colors.grey,
                      ),
                    ),
                  ),
                ),
                Expanded(
                  child: Center(
                    child: Text(
                      DateFormat('MMMM, yyyy').format(currentMonthDate),
                      style: TextStyle(
                        fontWeight: FontWeight.w500,
                        fontSize: 15.sp,
                        color: Colors.white,
                      ),
                    ),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Container(
                    height: 38,
                    width: 38,
                    decoration: BoxDecoration(
                      borderRadius:
                          const BorderRadius.all(Radius.circular(24.0)),
                      border: Border.all(
                        color: HotelAppTheme.buildLightTheme().dividerColor,
                      ),
                    ),
                    child: InkWell(
                      borderRadius:
                          const BorderRadius.all(Radius.circular(24.0)),
                      onTap: () {
                        if (mounted) {
                          setState(() {
                            if (getCurMonthIsInMinMaxRange(DateTime(
                                currentMonthDate.year,
                                currentMonthDate.month + 2,
                                0))) {
                              currentMonthDate = DateTime(currentMonthDate.year,
                                  currentMonthDate.month + 2, 0);
                              setListOfDate(currentMonthDate);
                            }
                          });
                        }
                      },
                      child: const Icon(
                        Icons.keyboard_arrow_right,
                        color: Colors.grey,
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
          Padding(
            padding: const EdgeInsets.only(right: 8, left: 8, bottom: 8),
            child: Row(
              children: getDaysNameUI(),
            ),
          ),
          Padding(
            padding: const EdgeInsets.only(right: 8, left: 8),
            child: Column(
              children: getDaysNoUI(),
            ),
          ),
        ],
      ),
    );
  }

  List<Widget> getDaysNameUI() {
    final List<Widget> listUI = <Widget>[];
    final weekendList = [5, 6];
    for (int i = 0; i < 7; i++) {
      listUI.add(
        Expanded(
          child: Center(
            child: Text(
              DateFormat('EEE').format(dateList[i]),
              style: TextStyle(
                fontSize: 14.sp,
                fontWeight: FontWeight.w500,
                color: weekendList.contains(i)
                    ? HotelAppTheme.buildLightTheme().primaryColorDark
                    : Colors.white,
              ),
            ),
          ),
        ),
      );
    }
    return listUI;
  }

  List<Widget> getDaysNoUI() {
    final List<Widget> noList = <Widget>[];
    int count = 0;
    for (int i = 0; i < dateList.length / 7; i++) {
      final List<Widget> listUI = <Widget>[];
      for (int i = 0; i < 7; i++) {
        final DateTime date = dateList[count];
        listUI.add(
          Expanded(
            child: AspectRatio(
              aspectRatio: 1.0,
              child: Stack(
                children: <Widget>[
                  Padding(
                    padding: const EdgeInsets.only(top: 3, bottom: 3),
                    child: Padding(
                      padding: EdgeInsets.only(
                          top: 0,
                          bottom: 0,
                          left: isStartDateRadius(date) ? 4 : 0,
                          right: isEndDateRadius(date) ? 4 : 0),
                      child: Container(
                        decoration: BoxDecoration(
                          color: startDate != null && endDate != null
                              ? getIsItStartAndEndDate(date) ||
                                      getIsInRange(date)
                                  ? HotelAppTheme.buildLightTheme()
                                      .primaryColorDark
                                      .withOpacity(0.1)
                                  : Colors.transparent
                              : Colors.transparent,
                          borderRadius: BorderRadius.only(
                            bottomLeft: isStartDateRadius(date)
                                ? Radius.circular(15.r)
                                : const Radius.circular(0.0),
                            topLeft: isStartDateRadius(date)
                                ? Radius.circular(15.r)
                                : const Radius.circular(0.0),
                            topRight: isEndDateRadius(date)
                                ? Radius.circular(15.r)
                                : const Radius.circular(0.0),
                            bottomRight: isEndDateRadius(date)
                                ? Radius.circular(15.r)
                                : const Radius.circular(0.0),
                          ),
                        ),
                      ),
                    ),
                  ),
                  InkWell(
                    borderRadius: const BorderRadius.all(Radius.circular(32.0)),
                    onTap: () {
                      if (currentMonthDate.month == date.month) {
                        final DateTime? minimumDate = widget.minimumDate;
                        final DateTime? maximumDate = widget.maximumDate;
                        if (minimumDate != null && maximumDate != null) {
                          final DateTime newminimumDate = DateTime(
                              minimumDate.year,
                              minimumDate.month,
                              minimumDate.day - 1);
                          final DateTime newmaximumDate = DateTime(
                              maximumDate.year,
                              maximumDate.month,
                              maximumDate.day + 1);
                          if (date.isAfter(newminimumDate) &&
                              date.isBefore(newmaximumDate)) {
                            onDateClick(date);
                          }
                        } else if (minimumDate != null) {
                          final DateTime newminimumDate = DateTime(
                              minimumDate.year,
                              minimumDate.month,
                              minimumDate.day - 1);
                          if (date.isAfter(newminimumDate)) {
                            onDateClick(date);
                          }
                        } else if (maximumDate != null) {
                          final DateTime newmaximumDate = DateTime(
                              maximumDate.year,
                              maximumDate.month,
                              maximumDate.day + 1);
                          if (date.isBefore(newmaximumDate)) {
                            onDateClick(date);
                          }
                        } else {
                          onDateClick(date);
                        }
                      }
                    },
                    child: Padding(
                      padding: const EdgeInsets.all(2),
                      child: Container(
                        decoration: BoxDecoration(
                          color: getIsItStartAndEndDate(date)
                              ? HotelAppTheme.buildLightTheme().primaryColorDark
                              : Colors.transparent,
                          borderRadius: getStartOrEndPoint(date),
                          // border: Border.all(
                          //   color: getIsItStartAndEndDate(date)
                          //       ? Colors.white
                          //       : Colors.transparent,
                          //   width: 2,
                          // ),
                          // boxShadow: getIsItStartAndEndDate(date)
                          //     ? <BoxShadow>[
                          //         BoxShadow(
                          //             color: Colors.grey.withOpacity(0.6),
                          //             blurRadius: 4),
                          //       ]
                          //     : null,
                        ),
                        child: Center(
                          child: Text(
                            '${date.day}',
                            style: ceilStyle(date),
                          ),
                        ),
                      ),
                    ),
                  ),
                  Positioned(
                    bottom: 9,
                    right: 0,
                    left: 0,
                    child: Container(
                      height: 6,
                      width: 6,
                      decoration: BoxDecoration(
                          color: DateTime.now().day == date.day &&
                                  DateTime.now().month == date.month &&
                                  DateTime.now().year == date.year
                              ? getIsInRange(date)
                                  ? Colors.white
                                  : HotelAppTheme.buildLightTheme()
                                      .primaryColorDark
                              : Colors.transparent,
                          shape: BoxShape.circle),
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
        count += 1;
      }
      noList.add(Row(
        mainAxisAlignment: MainAxisAlignment.center,
        mainAxisSize: MainAxisSize.min,
        children: listUI,
      ));
    }
    return noList;
  }

  BorderRadius getStartOrEndPoint(DateTime date) {
    KLogUtil.log([startDate, endDate, KDateUtils.isSome(startDate, endDate)]);
    if (startDate.toString() == endDate.toString()) {
      return BorderRadius.all(
        Radius.circular(15.r),
      );
    } else if (getIsItStart(date)) {
      return BorderRadius.only(
        topLeft: Radius.circular(15.r),
        bottomLeft: Radius.circular(15.r),
      );
    } else {
      return BorderRadius.only(
        topRight: Radius.circular(15.r),
        bottomRight: Radius.circular(15.r),
      );
    }
  }

  // 日期每一格的样式
  TextStyle ceilStyle(DateTime date) {
    // 不能选择日期的样式
    if (!getIsInMinMaxRange(date)) {
      return TextStyle(
        color: Colors.grey.withOpacity(0.6),
        fontSize: MediaQuery.of(context).size.width > 360 ? 14.sp : 16.sp,
        fontWeight:
            getIsItStartAndEndDate(date) ? FontWeight.bold : FontWeight.normal,
      );
    }
    return TextStyle(
        color: getIsItStartAndEndDate(date) || getIsInRange(date)
            ? Colors.white
            : currentMonthDate.month == date.month
                ? Colors.white
                : Colors.grey.withOpacity(0.6),
        fontSize: MediaQuery.of(context).size.width > 360 ? 14.sp : 16.sp,
        fontWeight:
            getIsItStartAndEndDate(date) ? FontWeight.bold : FontWeight.normal);
  }

  bool getIsInMinMaxRange(DateTime date) {
    if (widget.minimumDate != null && widget.maximumDate != null) {
      if (date.isAfter(widget.minimumDate!) &&
          date.isBefore(widget.maximumDate!)) {
        return true;
      }
    }
    return false;
  }

  // 当前月份是否在
  bool getCurMonthIsInMinMaxRange(DateTime tgtMonth) {
    if (widget.minimumDate != null && widget.maximumDate != null) {
      if (tgtMonth.isAfter(DateTime(
              widget.minimumDate!.year, widget.minimumDate!.month, 0)) &&
          tgtMonth.isBefore(DateTime(
              widget.maximumDate!.year, widget.maximumDate!.month + 2, 0))) {
        return true;
      }
    }
    return false;
  }

  bool getIsInRange(DateTime date) {
    if (startDate != null && endDate != null) {
      if (date.isAfter(startDate!) && date.isBefore(endDate!)) {
        return true;
      }
    }
    return false;
  }

  bool getIsItStartAndEndDate(DateTime date) {
    if ((startDate != null &&
            startDate!.day == date.day &&
            startDate!.month == date.month &&
            startDate!.year == date.year) ||
        (endDate != null &&
            endDate!.day == date.day &&
            endDate!.month == date.month &&
            endDate!.year == date.year)) return true;
    return false;
  }

  bool getIsItStart(DateTime date) {
    if (startDate != null &&
        startDate!.day == date.day &&
        startDate!.month == date.month &&
        startDate!.year == date.year) return true;
    return false;
  }

  bool isStartDateRadius(DateTime date) {
    if (startDate != null &&
        startDate!.day == date.day &&
        startDate!.month == date.month) {
      return true;
    } else if (date.weekday == 1) {
      return true;
    } else {
      return false;
    }
  }

  bool isEndDateRadius(DateTime date) {
    if (endDate != null &&
        endDate!.day == date.day &&
        endDate!.month == date.month) {
      return true;
    } else if (date.weekday == 7) {
      return true;
    } else {
      return false;
    }
  }

  void onDateClick(DateTime date) {
    if (startDate == null) {
      startDate = date;
    } else if (startDate != date && endDate == null) {
      endDate = date;
    } else if (startDate!.day == date.day && startDate!.month == date.month) {
      // startDate = null;
      endDate = startDate;
    } else if (endDate != null &&
        endDate!.day == date.day &&
        endDate!.month == date.month) {
      if (endDate != null) {
        startDate = endDate;
      } else {
        endDate = null;
      }
    }
    if (startDate == null && endDate != null) {
      startDate = endDate;
      endDate = null;
    }
    if (startDate != null && endDate != null) {
      if (!endDate!.isAfter(startDate!)) {
        final DateTime d = startDate!;
        startDate = endDate;
        endDate = d;
      }
      if (date.isBefore(startDate!)) {
        startDate = date;
      } else if (date.isAfter(endDate!)) {
        endDate = date;
      } else {
        final int daysToStartDate = startDate!.difference(date).inDays.abs();
        final int daysToEndDate = endDate!.difference(date).inDays.abs();
        daysToStartDate > daysToEndDate ? endDate = date : startDate = date;
      }
    }
    if (mounted) {
      setState(
        () {
          if (startDate != null && endDate != null) {
            try {
              widget.startEndDateChange(startDate!, endDate!);
            } catch (_) {}
          }
          if (startDate != null) {
            try {
              widget.startDateChange(startDate!);
            } catch (_) {}
          }
          if (endDate != null) {
            try {
              widget.endDateChange(endDate!);
            } catch (_) {}
          }
        },
      );
    }
  }
}

hotel_app_theme.dart

import 'package:flutter/material.dart';

class HotelAppTheme {
  static TextTheme _buildTextTheme(TextTheme base) {
    const String fontName = 'WorkSans';
    return base.copyWith(
      displayLarge: base.displayLarge?.copyWith(fontFamily: fontName),
      displayMedium: base.displayMedium?.copyWith(fontFamily: fontName),
      displaySmall: base.displaySmall?.copyWith(fontFamily: fontName),
      headlineMedium: base.headlineMedium?.copyWith(fontFamily: fontName),
      headlineSmall: base.headlineSmall?.copyWith(fontFamily: fontName),
      titleLarge: base.titleLarge?.copyWith(fontFamily: fontName),
      labelLarge: base.labelLarge?.copyWith(fontFamily: fontName),
      bodySmall: base.bodySmall?.copyWith(fontFamily: fontName),
      bodyLarge: base.bodyLarge?.copyWith(fontFamily: fontName),
      bodyMedium: base.bodyMedium?.copyWith(fontFamily: fontName),
      titleMedium: base.titleMedium?.copyWith(fontFamily: fontName),
      titleSmall: base.titleSmall?.copyWith(fontFamily: fontName),
      labelSmall: base.labelSmall?.copyWith(fontFamily: fontName),
    );
  }

  static ThemeData buildLightTheme() {
    // #54D3C2
    // #54D3C2
    // #4677FF
    const Color primaryColor = Color(0xff1C1D1F);
    const Color secondaryColor = Color(0xff1C1D1F);
    const Color primaryColorDark = Color(0xff4677FF);
    final ColorScheme colorScheme = const ColorScheme.light().copyWith(
      primary: primaryColor,
      secondary: secondaryColor,
    );
    final ThemeData base = ThemeData.light();
    return base.copyWith(
      primaryColor: primaryColor,
      primaryColorDark: primaryColorDark,
      indicatorColor: Colors.white,
      splashColor: Colors.white24,
      splashFactory: InkRipple.splashFactory,
      canvasColor: Colors.white,
      // #F6F6F6
      scaffoldBackgroundColor: const Color(0xFFF6F6F6),
      buttonTheme: ButtonThemeData(
        colorScheme: colorScheme,
        textTheme: ButtonTextTheme.primary,
      ),
      textTheme: _buildTextTheme(base.textTheme),
      primaryTextTheme: _buildTextTheme(base.primaryTextTheme),
      platform: TargetPlatform.iOS,
      colorScheme: colorScheme
          .copyWith(background: const Color(0xff1C1D1F))
          // #B00020
          .copyWith(error: const Color(0xFFB00020)),
    );
  }
}

RangePicker.dart  这个文件是使用的地方 这里还使用到了  getx 的组件 从底部弹出文章来源地址https://www.toymoban.com/news/detail-645941.html

// ignore_for_file: file_names

import 'package:app/gen/assets.gen.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';

import 'calendar_popup_view.dart';

class RangePicker extends StatefulWidget {
  RangePicker({super.key, required this.apply});

  final Function(DateTime, DateTime) apply;
  @override
  State<RangePicker> createState() => _RangePickerState();
}

class _RangePickerState extends State<RangePicker> {
  DateTime startDate = DateTime.now().subtract(const Duration(days: 90));
  DateTime endDate = DateTime.now();

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        openCalendarPopupView(context);
      },
      child: Row(
        children: [
          Text(
            "${DateFormat('MM/dd').format(startDate)} - ${DateFormat('MM/dd').format(endDate)}",
            style: TextStyle(
              color: const Color(0xff676970),
              fontWeight: FontWeight.w500,
              fontSize: 12.sp,
            ),
          ),
          SizedBox(
            width: 4.w,
          ),
          Assets.icon.botomArrowhead.image(width: 17.w),
        ],
      ),
    );
  }

  void openCalendarPopupView(BuildContext context) {
    Get.bottomSheet(
      isScrollControlled: true,
      StatefulBuilder(builder: (context, state) {
        return CalendarPopupView(
          state: state,
          minimumDate: DateTime.now().subtract(const Duration(days: 365)),
          maximumDate: DateTime.now(),
          initialEndDate: endDate,
          initialStartDate: startDate,
          onApplyClick: (DateTime startData, DateTime endData) {
            if (mounted) {
              setState(() {
                startDate = startData;
                endDate = endData;
              });
              state(() {
                startDate = startData;
                endDate = endData;
              });
              widget.apply(startDate, endDate);
            }
          },
          onCancelClick: () {},
        );
      }),
    );
  }
}

到了这里,关于flutter 手写日历组件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 31 3D日历组件

    实现了一个3D文字旋转的效果,当鼠标悬停在容器上时,最后一个文字会旋转630度,而其他文字会逐渐旋转到水平面上方。 这段代码是设置全局样式,将所有元素的外边距、内边距和盒模型设置为0,以便更好地控制元素的大小和位置。 这段代码是设置页面的基本样式,将页

    2024年01月18日
    浏览(37)
  • 小程序自定义日历组件

    2024年02月03日
    浏览(36)
  • vue自定义日历小组件

    自己开发的项目需要用到类似博客侧边栏小日历组件,觉得自己造一个比较随心所欲,更能满足自己的需求,所以决定自己开发一个。最终效果如图所示。 我的这个日历组件主要分为导航栏区和主要内容区,导航栏按钮样式什么的都是自定义的,很简单,源码有就不罗嗦。主

    2023年04月08日
    浏览(39)
  • 小程序日期(日历)时间 选择器组件

    封装一个小程序日期(日历)时间 选择器组件 简要说明: 一共两个版本 ,date-time-picker 和 date-time-picker-plus. date-time-picker 弹窗层是 基于 vant-weapp 的 van-popup 组件实现的 date-time-picker-plus 弹窗层是 基于 小程序 自带的 page-container 组件来实现的 * 注意:date-time-picker 需要下载 v

    2024年02月01日
    浏览(49)
  • flutter手写一个底部导航栏

    使用了一下flutter提供的导航栏,NavigationBar,不过感觉使用起来不是很方便。 譬如说: 不能直接使用图片资源,需要中间加几层转换把图片转化成icon 文本大小及颜色不太好控制 状态栏的上边来一个横线也没有相应的样式,等等。 因此想来想去还是自己写一个吧。 效果如下

    2024年02月12日
    浏览(40)
  • Unity 日历插件组件-日期选择器2D(二)

    提示:源码附在文后~大家互相学习 目录 前言 一、组件结构 二、使用步骤 1.脚本列表 2.绑定说明 1.外层作为总控制层 2.选择日期模块 总结 刚开始使用Unity开发项目,目前工作需求以Unity2D开发为主!发现在以Unity开发的管理系统中,时常要用到日期选择的工具!所以归类提炼

    2024年02月07日
    浏览(40)
  • ElementUI中的日历组件加载无效的问题

      在ElementUI中提供了一个日历组件。在某些场景下还是比较有用的。只是在使用的时候会有些下坑,大家要注意下。   官网提供的信息比较简介。我们在引入到项目中使用的时候可以能会出现下面的错误提示。 提示你不能识别这个标签。这时我们需要收到的引入这个组

    2024年02月11日
    浏览(30)
  • Flutter笔记:手写一个简单的画板工具

    Flutter笔记 手写一个简单的画板工具 作者 : 李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 : 291148484@163.com 本文地址 :https://blog.csdn.net/qq_28550263/article/details/133418742 在本文中,我们将一起开发一个基本的Flutter画板应用,用户可以在画板上自由绘制,选择不同的颜色来绘

    2024年02月07日
    浏览(35)
  • 小程序自定义日历组件,可设置区间选择范围

    文档: https://treadpit.github.io/wx_calendar/v2/guide.html#%E5%BC%95%E5%85%A5%E7%BB%84%E4%BB%B6 1. 将  calendar  文件夹拷贝至自己的组件目录,页面  json  文件中配置组件,组件路径根据项目实际情况填写 2. 在页面  wxml  中引入组件 此时运行小程序,可以看到日历组件已经渲染出来了,可以做

    2024年02月11日
    浏览(38)
  • 用 ElementPlus 的日历组件 Calendar 自定义渲染

    使用 ElementPlus中的 Calendar 组件完成自定义渲染 1. 英文改为中文 转为中文的方式:用 ElementPlus的日历组件如何改为中文 2. 修改样式 附源码 3. 自定义头部 4. 增删改功能接入

    2024年04月17日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包