how to remove widget based on it's index in flutter

Issue

I’ve question about how to close the appropriate widget based on the close button index. here in this image, you can see the output so here I am adding some widget using add button which located inside app bar now i’ve added close button inside the container when the user pressed the close button it will remove that container.

Here is the image of output :

enter image description here

Here is the code i’ve tried

class BspUnlicensedSignupPage extends StatefulWidget {
  static const String routeName = "/bspUnlicensedSignup";
  final BspSignupCommonModel bspSignupCommonModel;

  BspUnlicensedSignupPage({
    Key key,
    @required this.bspSignupCommonModel,
  }) : super(key: key);

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

class _BspUnlicensedSignupPageState extends State<BspUnlicensedSignupPage> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  List<Object> images = List<Object>();
  Future<File> _imageFile;
  bool autovalidate = false;
  bool informationislegitimate = false;
  DateTime expirydate1 = DateTime.now();
  DateTime expirydate2 = DateTime.now();

  final format = DateFormat("yyyy-MM-dd");
  final format2 = DateFormat("yyyy-MM-dd");

  String type2 = 'Passport';
  List<String> _type = <String>[
    '',
    'Passport',
    'Driving License',
    'Voter ID card',
    'Ration Card',
    'Aadhar',
    'Other Id',
  ];
  String type = 'Passport';
  var _myWidgets = List<Widget>();
  int _index = 3;
  final Map<int, String> identification1Values = Map();
  final Map<int, String> documentValues = Map();
  final Map<int, DateTime> expiryDateValues = Map();
  final Map<int, String> issuingAuthority = Map();
  final Map<int, String> identificationPicturesValues = Map();

  final List<TextEditingController> _documentControllers = List();
  final List<TextEditingController> _issuingauthoritytype = List();
  final List<TextEditingController> _expiryDate = List();
  final List<TextEditingController> _issuingauthority = List();
  final List<List<Object>> _identificationpictures = List();

  @override
  void initState() {
    super.initState();
    setState(() {
      images.add("Add Image");
      images.add("Add Image");
      images.add("Add Image");
      images.add("Add Image");
      images.add("Add Image");
    });
  }

  void _add() {
    int keyValue = _index;
    _myWidgets = List.from(_myWidgets)
      ..add(Column(
        key: Key("$keyValue"),
        children: <Widget>[
          SizedBox(height: 10),
          Container(
            // padding: EdgeInsets.fromLTRB(18,5,18,18),
            padding: EdgeInsets.all(15),
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(10),
              boxShadow: [
                BoxShadow(
                  color: Colors.black12,
                  blurRadius: 15,
                ),
              ],
            ),
            child: Column(
              children: <Widget>[
                Stack(
                  children: <Widget>[
                    Align(
                      alignment: Alignment.topRight,
                      child: GestureDetector(
                        child: Icon(Icons.close),
                        onTap: () {
                          print("CLose pressed");
                          _myWidgets.removeAt(_index);
                        },
                      ),
                    ),
                    SizedBox(
                      height: 10,
                    ),
                    Column(
                      children: <Widget>[
                        SizedBox(
                          height: 20,
                        ),
                        _buildidentificationtype1(keyValue),
                        _builddocumentnumber1(keyValue),
                        _builddate(keyValue),
                        _buildissuingauthority1(keyValue),
                        _buildidentificationpictures(keyValue),
                      ],
                    ),
                  ],
                )
              ],
            ),
          )
        ],
      ));

    setState(() => ++_index);
  }

  bool isClicked = false;

  Widget _buildidentificationtype1(int keyValue) {
    TextEditingController controller = TextEditingController();
    _issuingauthoritytype.add(controller);

    return FormBuilder(
      autovalidate: autovalidate,
      child: FormBuilderCustomField(
          attribute: "Business type",
          validators: [FormBuilderValidators.required()],
          formField: FormField(
            builder: (FormFieldState<dynamic> field) {
              return InputDecorator(
                decoration: InputDecoration(
                  prefixIcon: Icon(Icons.location_on),
                  labelText: "Business type",
                  errorText: field.errorText,
                ),
                isEmpty: type == '',
                child: new DropdownButtonHideUnderline(
                  child: new DropdownButton(
                    value: type,
                    isDense: true,
                    onChanged: (String newValue) {
                      setState(() {
                        type = controller.text = newValue;
                        field.didChange(newValue);
                      });
                    },
                    items: _type.map(
                      (String value) {
                        return new DropdownMenuItem(
                          value: value,
                          child: new Text(value),
                        );
                      },
                    ).toList(),
                  ),
                ),
              );
            },
          )),
    );
  }

  Widget _builddocumentnumber1(int keyValue) {
    TextEditingController controller = TextEditingController();
    _documentControllers.add(controller);
    return new TudoTextWidget(
      controller: controller,
      prefixIcon: Icon(FontAwesomeIcons.idCard),
      labelText: "Document Number",
      validator: Validators().validateLicenseno,
      onSaved: (val) {
        setState(() {
          documentValues[keyValue] = val;
        });
        // _licenseno = val;
      },
    );
  }

  Widget _builddate(int keyValue) {
    TextEditingController controller = TextEditingController();
    _expiryDate.add(controller);
    return DateTimeField(
      format: format,
      autocorrect: true,
      autovalidate: autovalidate,
      controller: controller,
      readOnly: true,
      decoration: InputDecoration(
          labelText: "Expiry Date",
          hintText: "Expiry Date",
          prefixIcon: Icon(
            FontAwesomeIcons.calendar,
            size: 24,
          )),
      onShowPicker: (context, currentValue) {
        return showDatePicker(
            context: context,
            firstDate: DateTime(1900),
            initialDate: currentValue ?? DateTime.now(),
            lastDate: DateTime.now());
      },
    );
  }

  Widget _buildissuingauthority1(int keyValue) {
    TextEditingController controller = TextEditingController();
    _issuingauthority.add(controller);
    return new TudoTextWidget(
      prefixIcon: Icon(FontAwesomeIcons.idCard),
      labelText: "Issuing Authority",
      validator: (val) => Validators.validateName(val, "Issuing Authority"),
      onSaved: (val) {
        setState(() {
          issuingAuthority[keyValue] = val;
        });
      },
      controller: controller,
    );
  }

  Widget _buildidentificationpictures(int keyValue) {
    return GridView.count(
      physics: NeverScrollableScrollPhysics(),
      shrinkWrap: true,
      crossAxisCount: 5,
      childAspectRatio: 1,
      children: List.generate(images.length, (index) {
        if (images[index] is ImageUploadModel) {
          ImageUploadModel uploadModel = images[index];

          return Card(
            clipBehavior: Clip.antiAlias,
            child: Stack(
              children: <Widget>[
                Image.file(
                  uploadModel.imageFile,
                  width: 300,
                  height: 300,
                ),
                Positioned(
                  right: 5,
                  top: 5,
                  child: InkWell(
                    child: Icon(
                      Icons.remove_circle,
                      size: 20,
                      color: Colors.red,
                    ),
                    onTap: () {
                      setState(() {
                        images.replaceRange(index, index + 1, ['Add Image']);
                      });
                    },
                  ),
                ),
              ],
            ),
          );
        } else {
          return Card(
            child: IconButton(
              icon: Icon(Icons.add),
              onPressed: () {
                _onAddImageClick(index);
              },
            ),
          );
        }
      }),
    );
  }

  @override
  Widget build(BuildContext context) {
    final appBar = AppBar(
      title: Text("BSP Unlicensed Details"),
      leading: IconButton(
        icon: Icon(Icons.arrow_back_ios),
        onPressed: () {
          NavigationHelper.navigatetoBack(context);
        },
      ),
      actions: <Widget>[IconButton(icon: Icon(Icons.add), onPressed: _add)],
      centerTitle: true,
    );
    final bottomNavigationBar = Container(
      color: Colors.transparent,
      height: 56,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          new FlatButton.icon(
            icon: Icon(Icons.close),
            label: Text('Clear'),
            color: Colors.redAccent,
            textColor: Colors.black,
            padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(7),
            ),
            onPressed: () {},
          ),
          new FlatButton.icon(
              icon: Icon(FontAwesomeIcons.arrowCircleRight),
              label: Text('Next'),
              color: colorStyles["primary"],
              padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
              textColor: Colors.white,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(7),
              ),
              onPressed: () async {
                setState(() {
                  autovalidate = !autovalidate;
                });
                if (_formKey.currentState.validate()) {
                  BspSignupCommonModel model = widget.bspSignupCommonModel;
                  for (var i = 0; i < _myWidgets.length; i++) {
                    String document = _documentControllers[i].text;
                    String issuingAuthorityType = _issuingauthoritytype[i].text;
                    String expiryDate = _expiryDate[i].text;
                    String issuingAuthority = _issuingauthority[i].text;
                    //  String picture = _identificationpictures[i].text;
                    print('Document: $document');
                    print('IssuingAuthorityType: $issuingAuthorityType');
                    print('ExpiryDate: $expiryDate');
                    print('IssuingAuthority: $issuingAuthority');
                    print('Picture: ${_identificationpictures.length}');
                    print(_myWidgets.length);
                    List<Licensed> listOfLicenses = new List<Licensed>();

                    Licensed licensed = new Licensed(
                        bspLicenseNumber: document,
                        bspAuthority: issuingAuthority,
                        bspExpiryDate: expiryDate,
                        bspIssuing: issuingAuthorityType);

                    licensed.bspLicenseNumber = _documentControllers[i].text;
                    licensed.bspExpiryDate = _expiryDate[i].text;
                    licensed.bspIssuing = _issuingauthoritytype[i].text;
                    licensed.bspAuthority = _issuingauthority[i].text;
                    listOfLicenses.add(licensed);
                    model.unlicensed = listOfLicenses;
                  }

                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => BspLicensedSignupTermsPage(
                              bspSignupCommonModel: model)));
                }
              }),
        ],
      ),
    );
    return new Scaffold(
      appBar: appBar,
      bottomNavigationBar: bottomNavigationBar,
      body: Container(
        height: double.infinity,
        width: double.infinity,
        child: Form(
            autovalidate: autovalidate,
            key: _formKey,
            child: Stack(
              children: <Widget>[
                Column(
                  children: <Widget>[
                    Expanded(
                      child: SizedBox(
                        child: ListView(
                          padding: const EdgeInsets.all(18.0),
                          children: _myWidgets,
                        ),
                      ),
                    ),
                  ],
                )
              ],
            )),
      ),
    );
  }
}

Solution

Edit: It seems that you will need to use a Map instead of a List because if you remove an item the indexes could change.

You could do something like this: int keyValue = ++_lastKey;where _lastKey would be a variable that you increment every time you add an item and it will work as unique identifier

Then instead of _myWidgets.removeAt(keyValue); call this _myWidgetsMap.remove(keyValue) inside a setState(), like this:

setState(() {
  _myWidgetsMap.remove(keyValue);
});

And you should call the code inside _add() inside a setState()


But I recommend you to build your widgets according to a list of information, instead of a list of widgets. This way when you change the information, the widgets would adapt correctly.

Answered By – Pablo Barrera

Answer Checked By – Mildred Charles (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *