flutter_form_builder icon indicating copy to clipboard operation
flutter_form_builder copied to clipboard

What is the bast practice for horizontal scroll?

Open dfdgsdfg opened this issue 3 years ago • 0 comments

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?

dfdgsdfg avatar Oct 09 '22 13:10 dfdgsdfg