Как обрабатывать динамически генерируемый контроллер виджетов во флаттере - PullRequest
0 голосов
/ 14 октября 2019

У меня есть одна страница на этой странице. Пользователь может добавить контроллер с помощью кнопки «Добавить», расположенной на панели приложений, поэтому, если пользователь хочет использовать этот контроллер в пять раз больше, пользователь может добавить этот контроллер и использовать, но как это сделать? Я получаю данные контроллера, используя массив. надеюсь, вы понимаете вопрос.

в этом коде, я добавил кнопку добавления и контроллер, когда пользователь нажимает кнопку добавления, он сможет добавить больше контроллеров, так как я управляю контроллерами.

Вот код, который я пробовал

import 'dart:io';

import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
import 'package:flutter/material.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:image_picker/image_picker.dart';
import 'package:intl/intl.dart';
import 'package:tudo/src/modules/bsp_signup/bsp_licensed_signup_terms/bsp_licensed_signup_terms_page.dart';
import 'package:tudo/src/modules/bsp_signup/bsp_signup_common_model.dart';
import 'package:tudo/src/styles/colors.dart';
import 'package:tudo/src/utils/app_constants_value.dart';

import 'package:tudo/src/utils/navigation_helper.dart';
import 'package:tudo/src/utils/validator.dart';
import 'package:tudo/src/widgets/tudo_selection_widget/TudoConditionWidget.dart';
import 'package:tudo/src/widgets/tudo_text_widget/TudoTextWidget.dart';

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;
  @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");
    });
  }

  bool informationislegitimate = false;
  DateTime expirydate1 = DateTime.now();
  DateTime expirydate2 = DateTime.now();

  final format = DateFormat("yyyy-MM-dd");
  final format2 = DateFormat("yyyy-MM-dd");
  final TextEditingController clrbusinesslicense = TextEditingController();
  final TextEditingController clrbusinesslicense2 = TextEditingController();
  final TextEditingController clrissuingauthority = TextEditingController();
  final TextEditingController clrissuingauthority2 = TextEditingController();
  String _licenseno;
  String _licenseno2;
  String _illusingauthority;
  String _illusingauthority2;
  List<String> _type2 = <String>[
    '',
    'Passport',
    'Driving License',
    'Voter ID card',
    'Ration Card',
    'Aadhar',
    'Other Id',
  ];
  String type2 = 'Passport';
  List<String> _type = <String>[
    '',
    'Passport',
    'Driving License',
    'Voter ID card',
    'Ration Card',
    'Aadhar',
    'Other Id',
  ];
  String type = 'Passport';
  Map<String, String> _formdata = {};
  var _myWidgets = List<Widget>();
  int _index = 1;

  void _add() {
    int keyValue = _index;
    _myWidgets = List.from(_myWidgets)
      ..add(Column(
        key: Key("${keyValue}"),
        children: <Widget>[
          _buildidentificationtype1(),
          _builddocumentnumber1(),
          _buildexpirydate1(),
          _buildissuingauthority1(),
          _buildidentificationpictures(),
          _buildinformationislegitmate(),
        ],
      ));

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

  bool isClicked = false;
  _add1() {
    setState(() {
      isClicked = true;
      ++_index;
    });
  }

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

  Widget _builddocumentnumber1() {
    return new TudoTextWidget(
      controller: clrbusinesslicense,
      prefixIcon: Icon(FontAwesomeIcons.idCard),
      labelText: AppConstantsValue.appConst['unlicensedsignup']
          ['documentnumber1']['translation'],
      hintText: AppConstantsValue.appConst['unlicensedsignup']
          ['documentnumber1']['translation'],
      validator: Validators().validateLicenseno,
      onSaved: (val) {
        _licenseno = val;
      },
    );
  }

  Widget _buildexpirydate1() {
    return FormField(builder: (FormFieldState state) {
      return DateTimeField(
        decoration: InputDecoration(
            labelText: expirydate1.toString(),
            prefixIcon: Icon(Icons.date_range)),
        format: format,
        onShowPicker: (context, currentValue) async {
          final DateTime picked = await showDatePicker(
              context: context,
              initialDate: expirydate1,
              firstDate: DateTime(1900),
              lastDate: DateTime.now());
          if (picked != null && picked != expirydate1)
            setState(() {
              expirydate1 = picked;
              print(expirydate1);
            });
        },
      );
    });
  }

  Widget _buildissuingauthority1() {
    return new TudoTextWidget(
      prefixIcon: Icon(FontAwesomeIcons.idCard),
      labelText: AppConstantsValue.appConst['unlicensedsignup']
          ['issuingauthority1']['translation'],
      hintText: AppConstantsValue.appConst['unlicensedsignup']
          ['issuingauthority1']['translation'],
      validator: (val) => Validators.validateName(val, "Issuing Authority"),
      onSaved: (val) {
        _illusingauthority = val;
      },
      controller: clrissuingauthority,
    );
  }

  Widget _buildidentificationtype2() {
    return FormBuilder(
      autovalidate: true,
      child: FormBuilderCustomField(
          attribute: "Identification type",
          validators: [FormBuilderValidators.required()],
          formField: FormField(
            builder: (FormFieldState<dynamic> field) {
              return InputDecorator(
                decoration: InputDecoration(
                  prefixIcon: Icon(Icons.location_on),
                  labelText: AppConstantsValue.appConst['unlicensedsignup']
                      ['identificationtype2']['translation'],
                  hintText: AppConstantsValue.appConst['unlicensedsignup']
                      ['identificationtype2']['translation'],
                  errorText: field.errorText,
                ),
                isEmpty: type2 == '',
                child: new DropdownButtonHideUnderline(
                  child: new DropdownButton(
                    value: type2,
                    isDense: true,
                    onChanged: (String newValue) {
                      setState(() {
                        type2 = newValue;
                        field.didChange(newValue);
                      });
                    },
                    items: _type2.map(
                      (String value) {
                        return new DropdownMenuItem(
                          value: value,
                          child: new Text(value),
                        );
                      },
                    ).toList(),
                  ),
                ),
              );
            },
          )),
    );
  }

  Widget _builddocumentnumber2() {
    return new TudoTextWidget(
      controller: clrbusinesslicense2,
      prefixIcon: Icon(FontAwesomeIcons.idCard),
      labelText: AppConstantsValue.appConst['unlicensedsignup']
          ['documentnumber2']['translation'],
      validator: Validators().validateLicenseno,
      onSaved: (val) {
        _licenseno2 = val;
      },
    );
  }

  Widget _buildexpirydate2() {
    return FormField(builder: (FormFieldState state) {
      return DateTimeField(
        decoration: InputDecoration(
            labelText: expirydate2.toString(),
            prefixIcon: Icon(Icons.date_range)),
        format: format2,
        onShowPicker: (context, currentValue) async {
          final DateTime picked = await showDatePicker(
            context: context,
            initialDate: expirydate2,
            firstDate: DateTime(1900),
            lastDate: DateTime.now(),
          );
          if (picked != null && picked != expirydate2)
            setState(() {
              expirydate2 = picked;
              print(expirydate2);
            });
        },
      );
    });
  }

  Widget _buildissuingauthority2() {
    return new TudoTextWidget(
      controller: clrissuingauthority2,
      prefixIcon: Icon(FontAwesomeIcons.idCard),
      labelText: AppConstantsValue.appConst['unlicensedsignup']
          ['issuingauthority2']['translation'],
      validator: (val) => Validators.validateName(val, "Issuing authority"),
      onSaved: (val) {
        _illusingauthority2 = val;
      },
    );
  }

  Widget _buildidentificationpictures() {
    return GridView.count(
      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: 100,
                  height: 100,
                ),
                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);
              },
            ),
          );
        }
      }),
    );
  }

  Future _onAddImageClick(int index) async {
    setState(() {
      _imageFile = ImagePicker.pickImage(source: ImageSource.gallery);
      getFileImage(index);
    });
  }

  void getFileImage(int index) async {
//    var dir = await path_provider.getTemporaryDirectory();

    _imageFile.then((file) async {
      setState(() {
        ImageUploadModel imageUpload = new ImageUploadModel();
        imageUpload.isUploaded = false;
        imageUpload.uploading = false;
        imageUpload.imageFile = file;
        imageUpload.imageUrl = '';
        images.replaceRange(index, index + 1, [imageUpload]);
      });
    });
  }

  Widget _buildinformationislegitmate() {
    return TudoConditionWidget(
      text:
          "Above entered Identity information is legitimate and accurate to my knowledge",
    );
  }

  @override
  Widget build(BuildContext context) {
    final appBar = AppBar(
      title: Text("BSP Unlicensed Signup"),
      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,
      //margin: EdgeInsets.symmetric(vertical: 24, horizontal: 12),

      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          new FlatButton.icon(
            icon: Icon(Icons.close),
            label: Text('Clear'),
            textColor: Colors.black,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(7),
            ),
            onPressed: () {},
          ),
          new FlatButton.icon(
              icon: Icon(FontAwesomeIcons.arrowCircleRight),
              label: Text('Next'),
              color: colorStyles["primary"],
              textColor: Colors.white,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(7),
              ),
              onPressed: () async {
                if (_formKey.currentState.validate()) {
                  BspSignupCommonModel model = widget.bspSignupCommonModel;
                  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: true,
          key: _formKey,
          child: ListView(
            padding: const EdgeInsets.all(30.0),
            children: _myWidgets,
          ),
        ),
      ),
    );
  }
}

class ImageUploadModel {
  bool isUploaded;
  bool uploading;
  File imageFile;
  String imageUrl;

  ImageUploadModel({
    this.isUploaded,
    this.uploading,
    this.imageFile,
    this.imageUrl,
  });
}

Ответы [ 2 ]

1 голос
/ 16 октября 2019

Создайте список виджетов и переберите все виджеты, как показано ниже, чтобы получить значения из виджета

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;

                print(
                    'Document: $document\nIssuingAuthorityType: $issuingAuthorityType'
                    '\nExpiryDate: $expiryDate\nIssuingAuthority: $issuingAuthority'
                    '\nPicture: ${_identificationpictures.length}');
              }
1 голос
/ 14 октября 2019

В вашем случае вы могли бы сделать что-то вроде этого:

final List<TextEditingController> _controllers = List();

_add() {
  TextEditingController controller = TextEditingController();
  _controllers.add(controller);
  _buildTextField(controller); // Example call
}

// Example method
Widget _buildTextField(TextEditingController controller) {
  return TextField(
    controller: controller,
  );
}

Редактировать: используя ваш экзамен:

final List<TextEditingController> _controllers = List();

void _add() {
  TextEditingController controller = TextEditingController();
  _controllers.add(controller); //<--- add the new controller to the list

  int keyValue = _index;
  _myWidgets = List.from(_myWidgets)
    ..add(Column(
      key: Key("${keyValue}"),
      children: <Widget>[
        _buildidentificationtype1(),
        _builddocumentnumber1(controller), //<-- pass the new controller
        _buildexpirydate1(),
        _buildissuingauthority1(),
        _buildidentificationpictures(),
        _buildinformationislegitmate(),
      ],
    ));

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

Widget _builddocumentnumber1(TextEditingController controller) {
  return new TudoTextWidget(
    controller: controller, //<--- set the new controller
    prefixIcon: Icon(FontAwesomeIcons.idCard),
    labelText: AppConstantsValue.appConst['unlicensedsignup']
    ['documentnumber1']['translation'],
    hintText: AppConstantsValue.appConst['unlicensedsignup']
    ['documentnumber1']['translation'],
    validator: Validators().validateLicenseno,
    onSaved: (val) {
      _licenseno = val;
    },
  );
}

Edit2: Если вы хотите получить доступ ко всем значениям каждого виджета, вы можете поместить значения в Map, используя индекс в качестве ключа, например:

final Map<int, String> identification1Values = Map();
final Map<int, String> documentValues = Map();
final Map<int, DateTime> expiryDateValues = Map();
final Map<int, bool> isUsingAuthorityValues = Map();
final Map<int, String> identificationPicturesValues = Map();

void _add() {
  int keyValue = _index;
  _myWidgets = List.from(_myWidgets)
    ..add(Column(
      key: Key("${keyValue}"),
      children: <Widget>[
        _buildidentificationtype1(keyValue),
        _builddocumentnumber1(keyValue),
        _buildexpirydate1(keyValue),
        _buildissuingauthority1(keyValue),
        _buildidentificationpictures(keyValue),
        _buildinformationislegitmate(keyValue),
      ],
    ));

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

Затем внутрикаждого _build...() метода помещают значения в соответствующие им Map, например:

identification1Values[keyValue] = newValue;

Edit3: Убедитесь, что вы присваиваете значения внутри setState()

Также вам потребуется список контроллеров для каждого типа текстового поля, поэтому внутри каждого метода _build...() вы должны добавить новый контроллер в соответствующий список контроллеров, например:

final List<TextEditingController> _documentControllers = List();
final List<TextEditingController> _isUsingAuthorityControllers = List();

Widget _builddocumentnumber1(){
  TextEditingController controller = TextEditingController();
  _documentControllers.add(controller);
  return new TudoTextWidget(
    controller: controller,
    ...
  );
}

Widget _buildissuingauthority1() {
  TextEditingController controller = TextEditingController();
  _isUsingAuthorityControllers.add(controller);
  return new TudoTextWidget(
    ...
    controller: controller,
  );
}

Предложения:

  • Я рекомендую вам создать класс, содержащий все свойства, соответствующие значениям, а затем просто использовать один Map, чтобы поместить ихобъекты, заполненные всеми свойствами.
  • Вы можете создать собственный виджет, которыйсодержит все виджеты, которые вы добавляете при каждом нажатии кнопки добавления
  • Вместо того, чтобы хранить список виджетов, вы можете просто создать виджеты на основе значений Map
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...