Chris1234567899 / flutter_time_range_picker

A time range picker for Flutter
MIT License
33 stars 53 forks source link

Updating the wheel from outside the widget #30

Open lyngbach opened 2 years ago

lyngbach commented 2 years ago

Hello, thank you for this great plugin!

I am currently having trouble updating the the TimeRangePicker widget from outside of it.

My use case is that I use onStartChange and onEndChange to update some "external" DateTime variables. These variables are what initial sets the TimeRangePicker (which works fine). However when updating these variables from other sources like the showTimePicker I cant for the life of me update the state of this widget. I have tried all kinds of setState and force redrawn of the widget (I use the widget mode usecase), but no luck.

Am I missing something here? Is it not possible? A controller would be nice :)

TiagoHellebrandt commented 2 years ago

Hi @lyngbach, Have you tried to create a start and end in the parent widget state and pass on prop to TimeRangePicker? with that the onStartChange and onEndChange can create what it needs.

class TimePicker extends StatefulWidget {
  const TimePicker({
    Key? key,
    this.initialStart,
    this.initialEnd,
    this.onChange,
    this.onStartChange,
    this.onEndChange,
  }) : super(key: key);

  final TimeOfDay? initialStart;
  final TimeOfDay? initialEnd;
  final void Function(TimeOfDay start, TimeOfDay end)? onChange;
  final void Function(TimeOfDay start)? onStartChange;
  final void Function(TimeOfDay end)? onEndChange;

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

class _TimePickerState extends State<TimePicker> {
  late TimeOfDay start;
  late TimeOfDay end;

  @override
  void initState() {
    super.initState();

    if (widget.initialStart != null && widget.initialEnd != null) {
      setState(() {
        start = widget.initialStart!;
        end = widget.initialEnd!;
      });
    } else {
      setState(() {
        start = const TimeOfDay(hour: 0, minute: 0);
        end = const TimeOfDay(hour: 1, minute: 0);
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return TimeRangePicker(
      start: start,
      end: end,
      onStartChange: (TimeOfDay startTime) {
        setState(() {
          start = startTime;
        });
        widget.onStartChange?.call(startTime);
        widget.onChange?.call(startTime, end);
      },
      onEndChange: (TimeOfDay endTime) {
        setState(() {
          end = endTime;
        });
        widget.onEndChange?.call(endTime);
        widget.onChange?.call(start, endTime);
      },
    );
  }
}

This has worked for me.

Sorry for the English, I'm Brazilian, I'm still learning, I hope I helped.

TiagoHellebrandt commented 2 years ago

I've done other tests here, if you update the start or end state the widget will not update at all, as the start or end is passed to the child state only in initState.

You can force render the widget as in the article: https://jelenaaa.medium.com/how-to-force-widget-to-redraw-in-flutter-2eec703bc024

TiagoHellebrandt commented 2 years ago

However this is not ideal as it renders the entire widget.