Skip to content

Commit 615d560

Browse files
committed
Added new field type FormBuilderRangeSlider
1 parent 19b9416 commit 615d560

File tree

4 files changed

+151
-2
lines changed

4 files changed

+151
-2
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,9 @@ The currently supported fields include:
160160
* `FormBuilderCheckboxList` - List of Checkboxes for multiple selection
161161
* `FormBuilderChipsInput` - Takes a list of `Chip`s as input
162162
* `FormBuilderDateTimePicker` - For Date, Time and DateTime input
163-
* `FormBuilderDropdown` - Allow selection of one value from a list as a Dropdown
164-
* `FormBuilderRadio` - Allow selection of one value from a list of Radio Widgets
163+
* `FormBuilderDropdown` - Used to select one value from a list as a Dropdown
164+
* `FormBuilderRadio` - Used to select one value from a list of Radio Widgets
165+
* `FormBuilderRangeSlider` - Used to select a range from a range of values
165166
* `FormBuilderRate` - For selection of a numerical value as a rating
166167
* `FormBuilderSegmentedControl` - For selection of a value from the `CupertinoSegmentedControl` as an input
167168
* `FormBuilderSignaturePad` - Presents a drawing pad on which user can doodle

example/lib/main.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,20 @@ class MyHomePageState extends State<MyHomePage> {
173173
labelText: "Number of somethings",
174174
),
175175
),
176+
FormBuilderRangeSlider(
177+
attribute: "slider",
178+
validators: [FormBuilderValidators.min(6)],
179+
onChanged: _onChanged,
180+
min: 0.0,
181+
max: 10.0,
182+
initialValue: RangeValues(4, 7),
183+
divisions: 20,
184+
activeColor: Colors.red,
185+
inactiveColor: Colors.pink[100],
186+
decoration: InputDecoration(
187+
labelText: "Number of somethings",
188+
),
189+
),
176190
FormBuilderCheckbox(
177191
attribute: 'accept_terms',
178192
initialValue: false,

lib/flutter_form_builder.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export './src/fields/form_builder_checkbox_list.dart';
99
export './src/fields/form_builder_date_time_picker.dart';
1010
export './src/fields/form_builder_dropdown.dart';
1111
export './src/fields/form_builder_radio.dart';
12+
export './src/fields/form_builder_range_slider.dart';
1213
export './src/fields/form_builder_rate.dart';
1314
export './src/fields/form_builder_segmented_control.dart';
1415
export './src/fields/form_builder_slider.dart';
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter/widgets.dart';
3+
import 'package:flutter_form_builder/flutter_form_builder.dart';
4+
5+
class FormBuilderRangeSlider extends StatefulWidget {
6+
final String attribute;
7+
final List<FormFieldValidator> validators;
8+
final RangeValues initialValue;
9+
final bool readonly;
10+
final InputDecoration decoration;
11+
final ValueChanged onChanged;
12+
final ValueTransformer valueTransformer;
13+
final num max;
14+
final num min;
15+
final int divisions;
16+
final Color activeColor;
17+
final Color inactiveColor;
18+
final ValueChanged<RangeValues> onChangeStart;
19+
final ValueChanged<RangeValues> onChangeEnd;
20+
final RangeLabels labels;
21+
final RangeSemanticFormatterCallback semanticFormatterCallback;
22+
23+
FormBuilderRangeSlider({
24+
@required this.attribute,
25+
@required this.min,
26+
@required this.max,
27+
@required this.initialValue,
28+
this.validators = const [],
29+
this.readonly = false,
30+
this.decoration = const InputDecoration(),
31+
this.divisions,
32+
this.onChanged,
33+
this.valueTransformer,
34+
this.activeColor,
35+
this.inactiveColor,
36+
this.onChangeStart,
37+
this.onChangeEnd,
38+
this.labels,
39+
this.semanticFormatterCallback,
40+
});
41+
42+
@override
43+
_FormBuilderRangeSliderState createState() => _FormBuilderRangeSliderState();
44+
}
45+
46+
class _FormBuilderRangeSliderState extends State<FormBuilderRangeSlider> {
47+
bool _readonly = false;
48+
final GlobalKey<FormFieldState> _fieldKey = GlobalKey<FormFieldState>();
49+
FormBuilderState _formState;
50+
RangeValues _initialValue;
51+
52+
@override
53+
void initState() {
54+
_formState = FormBuilder.of(context);
55+
_formState?.registerFieldKey(widget.attribute, _fieldKey);
56+
_initialValue = widget.initialValue ?? (_formState.initialValue.containsKey(widget.attribute) ? _formState.initialValue[widget.attribute] : null);
57+
super.initState();
58+
}
59+
60+
@override
61+
void dispose() {
62+
_formState?.unregisterFieldKey(widget.attribute);
63+
super.dispose();
64+
}
65+
66+
@override
67+
Widget build(BuildContext context) {
68+
_readonly = (_formState?.readonly == true) ? true : widget.readonly;
69+
70+
return FormField(
71+
key: _fieldKey,
72+
enabled: !_readonly,
73+
initialValue: _initialValue,
74+
validator: (val) {
75+
for (int i = 0; i < widget.validators.length; i++) {
76+
if (widget.validators[i](val) != null)
77+
return widget.validators[i](val);
78+
}
79+
return null;
80+
},
81+
onSaved: (val) {
82+
if (widget.valueTransformer != null) {
83+
var transformed = widget.valueTransformer(val);
84+
_formState?.setAttributeValue(widget.attribute, transformed);
85+
} else
86+
_formState?.setAttributeValue(widget.attribute, val);
87+
},
88+
builder: (FormFieldState<RangeValues> field) {
89+
return InputDecorator(
90+
decoration: widget.decoration.copyWith(
91+
enabled: !_readonly,
92+
errorText: field.errorText,
93+
),
94+
child: Container(
95+
padding: EdgeInsets.only(top: 10.0),
96+
child: Column(
97+
crossAxisAlignment: CrossAxisAlignment.start,
98+
children: [
99+
RangeSlider(
100+
values: field.value,
101+
min: widget.min,
102+
max: widget.max,
103+
divisions: widget.divisions,
104+
activeColor: widget.activeColor,
105+
inactiveColor: widget.inactiveColor,
106+
onChangeEnd: widget.onChangeEnd,
107+
onChangeStart: widget.onChangeStart,
108+
labels: widget.labels,
109+
semanticFormatterCallback: widget.semanticFormatterCallback,
110+
onChanged: _readonly
111+
? null
112+
: (RangeValues values) {
113+
FocusScope.of(context).requestFocus(FocusNode());
114+
field.didChange(values);
115+
if (widget.onChanged != null) widget.onChanged(values);
116+
},
117+
),
118+
Row(
119+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
120+
children: <Widget>[
121+
Text("${widget.min}"),
122+
Text("${field.value.start} - ${field.value.end}"),
123+
Text("${widget.max}"),
124+
],
125+
),
126+
],
127+
),
128+
),
129+
);
130+
},
131+
);
132+
}
133+
}

0 commit comments

Comments
 (0)