diff --git a/CHANGELOG.md b/CHANGELOG.md index d1b3440..fa5e2bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,5 +62,7 @@ * Addition of 'decoration' parameter to 'FlutterFormInputPassword' ## 2.7.1 +* Added Iconica CI and Iconica Linter -* Added Iconica CI and Iconica Linter \ No newline at end of file +## 3.0.0 +* Updated the FlutterFormInputSwitch to FlutterFormInputBool. This now includes a parameter to either show a checkbox or switch diff --git a/example/lib/main.dart b/example/lib/main.dart index 211cc22..7a60e3d 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -54,8 +54,8 @@ class _MyHomePageState extends State { child: Column( children: [ Container(height: 10), - const Text('FlutterFormInputSwitch'), - FlutterFormInputSwitch( + const Text('FlutterFormInputBool'), + FlutterFormInputBool( initialValue: true, onChanged: (v) { debugPrint('Switch changed to $v'); diff --git a/example/pubspec.lock b/example/pubspec.lock index 4365e71..6787658 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -68,7 +68,7 @@ packages: path: ".." relative: true source: path - version: "2.7.0" + version: "3.0.0" flutter_lints: dependency: "direct dev" description: diff --git a/lib/src/inputs/switch/switch.dart b/lib/src/inputs/bool/bool.dart similarity index 58% rename from lib/src/inputs/switch/switch.dart rename to lib/src/inputs/bool/bool.dart index 0e7f920..e1cb13d 100644 --- a/lib/src/inputs/switch/switch.dart +++ b/lib/src/inputs/bool/bool.dart @@ -6,10 +6,10 @@ import 'package:flutter/material.dart'; -import 'package:flutter_input_library/src/inputs/switch/switch_field.dart'; +import 'package:flutter_input_library/src/inputs/bool/bool_field.dart'; -class FlutterFormInputSwitch extends StatelessWidget { - const FlutterFormInputSwitch({ +class FlutterFormInputBool extends StatelessWidget { + const FlutterFormInputBool({ super.key, this.label, this.onSaved, @@ -17,20 +17,35 @@ class FlutterFormInputSwitch extends StatelessWidget { this.onChanged, this.focusNode, this.initialValue = false, + this.widgetType = BoolWidgetType.switchWidget, + this.leftWidget, + this.rightWidget, }); + final Widget? label; final Function(bool?)? onSaved; final String? Function(bool?)? validator; final Function(bool?)? onChanged; final bool? initialValue; final FocusNode? focusNode; + final BoolWidgetType widgetType; + final Widget? leftWidget; + final Widget? rightWidget; @override - Widget build(BuildContext context) => SwitchFormField( + Widget build(BuildContext context) => BoolFormField( onSaved: (value) => onSaved?.call(value), onChanged: (value) => onChanged?.call(value), validator: (value) => validator?.call(value), initialValue: initialValue ?? false, focusNode: focusNode, + widgetType: widgetType, + leftWidget: leftWidget, + rightWidget: rightWidget, ); } + +enum BoolWidgetType { + switchWidget, + checkbox, +} diff --git a/lib/src/inputs/bool/bool_field.dart b/lib/src/inputs/bool/bool_field.dart new file mode 100644 index 0000000..e0eaa3e --- /dev/null +++ b/lib/src/inputs/bool/bool_field.dart @@ -0,0 +1,124 @@ +// SPDX-FileCopyrightText: 2022 Iconica +// +// SPDX-License-Identifier: BSD-3-Clause + +// ignore_for_file: avoid_positional_boolean_parameters + +import 'package:flutter/material.dart'; +import 'package:flutter_input_library/flutter_input_library.dart'; + +class BoolFormField extends FormField { + BoolFormField({ + required FormFieldSetter super.onSaved, + required FormFieldValidator super.validator, + super.key, + FocusNode? focusNode, + bool super.initialValue = false, + void Function(bool? value)? onChanged, + BoolWidgetType widgetType = BoolWidgetType.switchWidget, + Widget? leftWidget, + Widget? rightWidget, + }) : super( + builder: (FormFieldState state) => BoolWidget( + initialValue: initialValue, + state: state, + focusNode: focusNode, + onChanged: onChanged, + widgetType: widgetType, + errorText: state.errorText, + leftWidget: leftWidget, + rightWidget: rightWidget, + ), + ); +} + +class BoolWidget extends StatefulWidget { + const BoolWidget({ + required this.state, + this.initialValue = false, + this.onChanged, + this.focusNode, + this.widgetType = BoolWidgetType.switchWidget, + this.errorText, + this.leftWidget, + this.rightWidget, + super.key, + }); + + final bool initialValue; + final FormFieldState state; + final FocusNode? focusNode; + final void Function(bool? value)? onChanged; + final BoolWidgetType widgetType; + final String? errorText; + final Widget? leftWidget; + final Widget? rightWidget; + + @override + State createState() => _BoolWidgetState(); +} + +class _BoolWidgetState extends State { + late Widget child; + late bool value = widget.initialValue; + + void onChanged(bool value) { + widget.onChanged?.call(value); + + widget.state.didChange(value); + + setState(() { + this.value = value; + }); + } + + @override + Widget build(BuildContext context) { + var theme = Theme.of(context); + + late Widget child; + + switch (widget.widgetType) { + case BoolWidgetType.switchWidget: + child = Switch( + value: value, + focusNode: widget.focusNode, + onChanged: onChanged, + ); + break; + + case BoolWidgetType.checkbox: + child = Checkbox( + value: value, + focusNode: widget.focusNode, + onChanged: (bool? value) { + if (value != null) { + onChanged(value); + } + }, + ); + break; + } + + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + widget.leftWidget ?? const SizedBox.shrink(), + child, + widget.rightWidget ?? const SizedBox.shrink(), + ], + ), + if (widget.errorText != null) ...[ + Text( + widget.errorText!, + style: theme.inputDecorationTheme.errorStyle, + ), + ], + ], + ); + } +} diff --git a/lib/src/inputs/carousel/carousel_utils.dart b/lib/src/inputs/carousel/carousel_utils.dart index b0506dd..67be842 100644 --- a/lib/src/inputs/carousel/carousel_utils.dart +++ b/lib/src/inputs/carousel/carousel_utils.dart @@ -2,17 +2,17 @@ // // SPDX-License-Identifier: BSD-3-Clause -/// Converts an index of a set size to the corresponding index of a collection +/// Converts an index of a set size to the corresponding index of a collection /// of another size as if they were circular. /// -/// Takes a [position] from collection Foo, a [base] from where Foo's index -/// originated and the [length] of a second collection Baa, for which the +/// Takes a [position] from collection Foo, a [base] from where Foo's index +/// originated and the [length] of a second collection Baa, for which the /// correlating index is sought. /// -/// For example; We have a Carousel of 10000(simulating infinity) but only 6 -/// images. We need to repeat the images to give the illusion of a never -/// ending stream. By calling [getRealIndex] with position and base we get -/// an offset. This offset modulo our length, 6, will return a number between +/// For example; We have a Carousel of 10000(simulating infinity) but only 6 +/// images. We need to repeat the images to give the illusion of a never +/// ending stream. By calling [getRealIndex] with position and base we get +/// an offset. This offset modulo our length, 6, will return a number between /// 0 and 5, which represent the image to be placed in the given position. int getRealIndex(int position, int base, int? length) { var offset = position - base; diff --git a/lib/src/inputs/inputs.dart b/lib/src/inputs/inputs.dart index 16759bd..d5cdd9e 100644 --- a/lib/src/inputs/inputs.dart +++ b/lib/src/inputs/inputs.dart @@ -1,8 +1,8 @@ +export 'bool/bool.dart'; export 'carousel/carousel.dart'; export 'date_picker/date_picker.dart'; export 'number_picker/number_picker.dart'; export 'scroll_picker/scroll_picker.dart'; export 'slider/slider.dart'; -export 'switch/switch.dart'; export 'text/password.dart'; export 'text/plain_text.dart'; diff --git a/lib/src/inputs/number_picker/decimal_numberpicker.dart b/lib/src/inputs/number_picker/decimal_numberpicker.dart index dde8d7f..1a0b253 100644 --- a/lib/src/inputs/number_picker/decimal_numberpicker.dart +++ b/lib/src/inputs/number_picker/decimal_numberpicker.dart @@ -45,11 +45,11 @@ class DecimalNumberPicker extends StatelessWidget { final TextMapper? decimalTextMapper; final bool integerZeroPad; - /// Decoration to apply to central box where the selected integer value + /// Decoration to apply to central box where the selected integer value /// is placed final Decoration? integerDecoration; - /// Decoration to apply to central box where the selected decimal value + /// Decoration to apply to central box where the selected decimal value /// is placed final Decoration? decimalDecoration; diff --git a/lib/src/inputs/number_picker/infinite_listview.dart b/lib/src/inputs/number_picker/infinite_listview.dart index 30e8dd3..26b05aa 100644 --- a/lib/src/inputs/number_picker/infinite_listview.dart +++ b/lib/src/inputs/number_picker/infinite_listview.dart @@ -159,7 +159,7 @@ class InfiniteListViewState extends State { physics: scrollPhysics, viewportBuilder: (BuildContext context, ViewportOffset offset) => Builder( builder: (BuildContext context) { - /// Build negative [ScrollPosition] for the negative scrolling + /// Build negative [ScrollPosition] for the negative scrolling /// [Viewport]. var state = Scrollable.of(context); var negativeOffset = _InfiniteScrollPosition( @@ -170,13 +170,13 @@ class InfiniteListViewState extends State { negativeScroll: true, ); - /// Keep the negative scrolling [Viewport] positioned to the + /// Keep the negative scrolling [Viewport] positioned to the /// [ScrollPosition]. offset.addListener(() { negativeOffset._forceNegativePixels(offset.pixels); }); - /// Stack the two [Viewport]s on top of each other so they move in + /// Stack the two [Viewport]s on top of each other so they move in /// sync. return Stack( children: [ @@ -315,7 +315,7 @@ class InfiniteListViewState extends State { } } -/// Same as a [ScrollController] except it provides [ScrollPosition] objects +/// Same as a [ScrollController] except it provides [ScrollPosition] objects /// with infinite bounds. class InfiniteScrollController extends ScrollController { /// Creates a new [InfiniteScrollController] diff --git a/lib/src/inputs/switch/switch_field.dart b/lib/src/inputs/switch/switch_field.dart deleted file mode 100644 index fc4655e..0000000 --- a/lib/src/inputs/switch/switch_field.dart +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Iconica -// -// SPDX-License-Identifier: BSD-3-Clause - -import 'package:flutter/material.dart'; - -class SwitchFormField extends FormField { - SwitchFormField({ - required FormFieldSetter super.onSaved, - required FormFieldValidator super.validator, - super.key, - FocusNode? focusNode, - bool super.initialValue = false, - // ignore: avoid_positional_boolean_parameters - void Function(bool? value)? onChanged, - }) : super( - builder: (FormFieldState state) => SwitchWidget( - initialValue: initialValue, - state: state, - focusNode: focusNode, - onChanged: onChanged, - ), - ); -} - -class SwitchWidget extends StatefulWidget { - const SwitchWidget({ - required this.state, - this.initialValue = false, - this.onChanged, - this.focusNode, - super.key, - }); - - final bool initialValue; - final FormFieldState state; - final FocusNode? focusNode; - // ignore: avoid_positional_boolean_parameters - final void Function(bool? value)? onChanged; - - @override - State createState() => _SwitchWidgetState(); -} - -class _SwitchWidgetState extends State { - late bool value = widget.initialValue; - - @override - Widget build(BuildContext context) => Switch( - value: value, - focusNode: widget.focusNode, - onChanged: (bool value) { - widget.onChanged?.call(value); - - widget.state.didChange(value); - - setState(() { - this.value = value; - }); - }, - ); -} diff --git a/lib/src/inputs/text/password.dart b/lib/src/inputs/text/password.dart index cab9381..36f1414 100644 --- a/lib/src/inputs/text/password.dart +++ b/lib/src/inputs/text/password.dart @@ -5,8 +5,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -/// Generates a [TextFormField] for passwords. It requires a -/// [FlutterFormInputController] as the [controller] parameter and an +/// Generates a [TextFormField] for passwords. It requires a +/// [FlutterFormInputController] as the [controller] parameter and an /// optional [Widget] as [label] class FlutterFormInputPassword extends StatefulWidget { const FlutterFormInputPassword({ diff --git a/pubspec.yaml b/pubspec.yaml index ba2c3db..7286c19 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_input_library description: A new Flutter package project. -version: 2.7.1 +version: 3.0.0 repository: https://github.com/Iconica-Development/flutter_input_library environment: