flutter_form_builder
flutter_form_builder copied to clipboard
What is the bast practice for horizontal scroll?
Environment
Package version: 7.7.0
Describe your question
FormBuilderFilterChip has Wrap widget. If I try to make it horizontally scroll it may be like the below.
LayoutBuilder(
builder: (context, constraints) {
return SizedBox(
height: 100,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: constraints.maxHeight *3.2, // I don't know the children's exact width
),
child: FormBuilderFilterChip<String>(
name: 'filter',
options: ['a', 'bb', 'ccc'].map( // children's width is supposed to be dynamic
(x) {
return FormBuilderChipOption<String>(
value: x,
child: Text(x),
);
},
).toList(),
),
),
),
);
}
),
Or I can make FormBuilderFilterChipList like the one below.
class FormBuilderFilterChipList<T> extends FormBuilderField<List<T>> {
//TODO: Add documentation
final bool shouldRequestFocus;
final List<FormBuilderChipOption<T>> options;
final MaterialTapTargetSize? materialTapTargetSize;
final ChipThemeData? theme;
final IndexedWidgetBuilder separatorBuilder;
// List Settings
final Axis scrollDirection;
final EdgeInsets? padding;
final int? maxChips;
final ShapeBorder avatarBorder;
/// Creates field with chips that acts like a list checkboxes.
FormBuilderFilterChipList({
super.autovalidateMode,
super.decoration,
super.enabled,
super.focusNode,
super.initialValue,
super.key,
required super.name,
super.onChanged,
super.onReset,
super.onSaved,
super.validator,
super.valueTransformer,
this.theme,
this.padding,
required this.separatorBuilder,
required this.options,
this.avatarBorder = const CircleBorder(),
this.scrollDirection = Axis.horizontal,
this.materialTapTargetSize,
this.maxChips,
this.shouldRequestFocus = false,
}) : assert((maxChips == null) || ((initialValue ?? []).length <= maxChips)),
super(
builder: (FormFieldState<List<T>?> field) {
final state = field as _FormBuilderFilterChipState<T>;
final fieldValue = field.value ?? [];
return ListView.separated(
scrollDirection: scrollDirection, // make items horizontally scroll
separatorBuilder: separatorBuilder,
padding: padding,
itemCount: options.length,
itemBuilder: (context, i) {
final option = options[i];
return AppFilterChip(
theme: theme,
label: option,
selected: fieldValue.contains(option.value),
avatar: option.avatar,
onSelected: state.enabled &&
(null == maxChips ||
fieldValue.length < maxChips ||
fieldValue.contains(option.value))
? (selected) {
final currentValue = [...fieldValue];
if (selected) {
currentValue.add(option.value);
} else {
currentValue.remove(option.value);
}
if (shouldRequestFocus) {
state.requestFocus();
}
field.didChange(currentValue);
}
: null,
materialTapTargetSize: materialTapTargetSize,
);
},
);
},
);
@override
FormBuilderFieldState<AppFormBuilderFilterChip<T>, List<T>> createState() =>
_FormBuilderFilterChipState<T>();
}
class _FormBuilderFilterChipState<T>
extends FormBuilderFieldState<AppFormBuilderFilterChip<T>, List<T>> {}
Any other good practice?