i am getting some design issue in flutter multiselect

37 Views Asked by At
library multiselect;

import 'package:flutter/material.dart';
import 'package:states_rebuilder/states_rebuilder.dart';

class _TheState {}

var _theState = RM.inject(() => _TheState());

class RowWrapper extends InheritedWidget {
  final dynamic data;
  final bool Function() shouldNotify;
  RowWrapper({
    required Widget child,
    this.data,
    required this.shouldNotify,
  }) : super(child: child);

  @override
  bool updateShouldNotify(covariant InheritedWidget oldWidget) {
    return true;
  }
}

class _SelectRow extends StatefulWidget {
  final Function(bool) onChange;
  final bool selected;
  final String text;
  final String price;
  final Color textColor;
  final Function(String) onPriceChanged;

  _SelectRow({
    Key? key,
    required this.onChange,
    required this.selected,
    required this.text,
    required this.price,
    required this.onPriceChanged,
    this.textColor = Colors.blue,
  }) : super(key: key);

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

class _SelectRowState extends State<_SelectRow> {
  bool isSelected = false;

  @override
  void initState() {
    super.initState();
    isSelected = widget.selected;
  }

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () {
        isSelected = !isSelected;
        widget.onChange(isSelected);
        widget.onPriceChanged(widget.price);
        setState(() {});
      },
      child: Container(
        height: kMinInteractiveDimension,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            Checkbox(
              value: isSelected,
              onChanged: (x) {
                isSelected = x!;
                widget.onChange(x);
                widget.onPriceChanged(widget.price);
                setState(() {});
              },
            ),
            Text(
              widget.text,
              style: TextStyle(color: widget.textColor),
            ),
            SizedBox(width: 8), // Add some spacing
            Expanded(
              child: GestureDetector(
                onTap: () {
                  _editPrice(context);
                },
                child: Text(
                  widget.price,
                  style: TextStyle(color: widget.textColor),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  void _editPrice(BuildContext context) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text("Edit Price"),
          content: TextFormField(
            initialValue: widget.price,
            keyboardType: TextInputType.numberWithOptions(decimal: true),
            onChanged: (newPrice) {
              widget.onPriceChanged(newPrice);
              setState(() {});
            },
          ),
          actions: <Widget>[
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: Text("Cancel"),
            ),
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: Text("Save"),
            ),
          ],
        );
      },
    );
  }
}

class DropDownMultiSelect<T> extends StatefulWidget {
  final List<T> options;
  final List<T> selectedValues;
  final List<String> prices;
  //final Function(List<T>, List<String>) onChanged;
  final Function(List<T>, List<String>) onChanged;
  final bool isDense;
  final bool enabled;
  final InputDecoration? decoration;
  final String? whenEmpty;
  final Widget Function(List<T> selectedValues)? childBuilder;
  final Widget Function(T option)? menuItembuilder;
  final String Function(T? selectedOptions)? validator;
  final bool readOnly;
  final Widget? icon;
  final TextStyle? hintStyle;
  final Widget? hint;
  final TextStyle? selected_values_style;
  final List<String> selectedAmountValues;

  const DropDownMultiSelect({
    Key? key,
    required this.options,
    required this.selectedValues,
    required this.prices,
    required this.onChanged,
    this.whenEmpty,
    this.icon,
    this.hint,
    this.hintStyle,
    this.childBuilder,
    this.selected_values_style,
    this.menuItembuilder,
    this.isDense = true,
    this.enabled = true,
    this.decoration,
    this.validator,
    this.readOnly = false,
    required this.selectedAmountValues,
  }) : super(key: key);

  @override
  _DropDownMultiSelectState createState() => _DropDownMultiSelectState<T>();
}

class _DropDownMultiSelectState<TState>
    extends State<DropDownMultiSelect<TState>> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Stack(
        alignment: Alignment.centerLeft,
        children: [
          Container(
            child: DropdownButtonFormField<TState>(
              hint: widget.hint,
              style: widget.hintStyle,
              icon: widget.icon,
              validator: widget.validator != null ? widget.validator : null,
              decoration: widget.decoration != null
                  ? widget.decoration
                  : InputDecoration(
                      border: OutlineInputBorder(),
                      isDense: true,
                      contentPadding: EdgeInsets.symmetric(
                        vertical: 15,
                        horizontal: 10,
                      ),
                    ),
              isDense: widget.isDense,
              onChanged: widget.enabled ? (x) {} : null,
              isExpanded: false,
              value: widget.selectedValues.length > 0
                  ? widget.selectedValues[0] as TState
                  : null,
              selectedItemBuilder: (context) {
                return widget.options
                    .asMap()
                    .map(
                      (index, x) => MapEntry(
                        index,
                        DropdownMenuItem(
                          child: Container(
                            color: Colors.white,
                          ),
                        ),
                      ),
                    )
                    .values
                    .toList();
              },
              items: widget.options
                  .asMap()
                  .map(
                    (index, x) => MapEntry(
                      index,
                      DropdownMenuItem<TState>(
                        child: _theState.rebuild(() {
                          return widget.menuItembuilder != null
                              ? widget.menuItembuilder!(x)
                              : _SelectRow(
                                  selected: widget.selectedValues.contains(x),
                                  text: x.toString(),
                                  price: widget.prices[index],
                                  onChange: (isSelected) {
                                    var ns = widget.selectedValues;
                                    var sp = widget
                                        .selectedAmountValues; // Update this line

                                    if (isSelected) {
                                      ns.add(x);
                                      sp.add(widget.prices[index]);
                                    } else {
                                      ns.remove(x);
                                      sp.remove(widget.prices[index]);
                                    }

                                    widget.onChanged(ns, sp);
                                  },
                                  onPriceChanged: (newPrice) {
                                    setState(() {
                                      widget.prices[index] = newPrice;
                                    });
                                  },
                                );
                        }),
                        value: x,
                        onTap: !widget.readOnly
                            ? () {
                                if (widget.selectedValues.contains(x)) {
                                  var ns = widget.selectedValues;
                                  var sp = widget
                                      .selectedAmountValues; // Update this line
                                  ns.remove(x);
                                  sp.add(widget.prices[index]);
                                  widget.onChanged(ns, sp);
                                } else {
                                  var ns = widget.selectedValues;
                                  var sp = widget
                                      .selectedAmountValues; // Update this line
                                  ns.add(x);
                                  sp.add(widget.prices[index]);
                                  widget.onChanged(ns, sp);
                                }
                              }
                            : null,
                      ),
                    ),
                  )
                  .values
                  .toList(),
            ),
          ),
          _theState.rebuild(() => widget.childBuilder != null
              ? widget.childBuilder!(widget.selectedValues)
              : Padding(
                  padding: widget.decoration != null
                      ? widget.decoration!.contentPadding != null
                          ? widget.decoration!.contentPadding!
                          : EdgeInsets.symmetric(horizontal: 10)
                      : EdgeInsets.symmetric(horizontal: 20),
                  child: Padding(
                    padding: const EdgeInsets.only(right: 20),
                    child: Text(
                      widget.selectedValues.length > 0
                          ? widget.selectedValues
                              .map((e) => e.toString())
                              .reduce(
                                  (a, b) => a.toString() + ' , ' + b.toString())
                          : widget.whenEmpty ?? '',
                      style: widget.selected_values_style,
                    ),
                  ),
                )),
        ],
      ),
    );
  }
}
    List<String> fruits = ['Abhi', 'Avi', 'Nik', 'Sura'];
    List<String> selectedFruits = [];
    List<String> price = ['1.0', '2.0', '3.0', '4.0'];
    List<String> selectedPrices = [];
DropDownMultiSelect(
                                selectedAmountValues: selectedPrices,
                                prices: price,
                                options: fruits,
                                selectedValues: selectedFruits,
                                onChanged: (selectedFruits, selectedPrices) {
                                  print('Selected fruits: $selectedFruits');
                                  print('Selected prices: $selectedPrices');

                                  setState(() {
                                    selectedFruits = selectedFruits;
                                    selectedPrices = selectedPrices;
                                  });

                                  print(
                                      'You have selected $selectedFruits fruits with prices $selectedPrices.');
                                },
                              ),

Second one is my DropDownMultiSelect function which is calling the first one, which is a another file . it look like the image now if i click on 1.0 one alert dialog will be open and if i change the value to 11 and save it then my 1.0 is still showing and if i close that field and reopen then it work fine . I want to change the value 1.0 to 11 as soon as i would click the save button .

0

There are 0 best solutions below