Флаттер: сохранить данные в текстовом поле после установки - PullRequest
0 голосов
/ 08 ноября 2019
  1. У меня есть массив текстовых полей.
  2. Кнопка, которая добавляет новое текстовое поле в массив.
  3. Если вы добавляете данные в текстовое поле и добавляете новый элемент, нажимаякнопка добавления, добавленные данные исчезли.
  4. Функция кнопки имеет заданное положение, чтобы видеть новые элементы в массиве.
  5. Как добавить новые элементы в массив, сохраняя старые данныев текстовых полях?

start_workout.dart

    import 'package:flutter/material.dart';
import 'package:fultter_ultralifestyle/src/models/models.dart' show SetModel;
import 'package:fultter_ultralifestyle/src/presentation/widgets/dynamic_widget.dart';

class WorkoutStartScreen extends StatefulWidget {
  static const String routeName = "workoutStart";
  @override
  _WorkoutStartScreenState createState() => _WorkoutStartScreenState();
}

class _WorkoutStartScreenState extends State<WorkoutStartScreen> {
  final List<SetModel> sets = [
  ];

  void _addSet() {
    final id = sets.length;
    sets.add(SetModel(id: id, pounds: 0, reps: 0));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Workout tracker"),
        centerTitle: true,
      ),
      body: Container(
        child: Column(
          children: <Widget>[
            Expanded(
              child: ListView.builder(
                  itemCount: sets.length,
                  itemBuilder: (BuildContext context, int index) {
                    return DynamicWidget(
                      set: sets[index],
                      pos: index +1,
                      delete: () {
                        sets.removeAt(index);
                        setState(() {});
                      },
                    );
                  }),
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => _addSet(),
        child: Icon(Icons.add),
      ),
    );
  }
}

dynamic_widget.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fultter_ultralifestyle/src/models/models.dart';
import 'package:fultter_ultralifestyle/src/presentation/widgets/text_widget.dart';

class DynamicWidget extends StatelessWidget {
  final TextEditingController poundsController = TextEditingController();
  final TextEditingController repsController = TextEditingController();

  final SetModel set;
  final int pos;
  Function delete;

  DynamicWidget({
    Key key,
    @required this.set,
    @required this.pos,
    @required this.delete,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final Size size = MediaQuery.of(context).size;

    return Container(
      child: Column(
        children: <Widget>[
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                child: text(
                  caption: "SET $pos",
                ),
              ),
              SizedBox(width: 20.0),
              Container(
                width: size.width / 4,
                child: Column(
                  children: <Widget>[
                    TextField(
                      controller: poundsController,
                      keyboardType: TextInputType.number,
                      inputFormatters: [
                        WhitelistingTextInputFormatter.digitsOnly,
                      ],
                    ),
                    SizedBox(height: 10),
                    text(caption: "pounds".toUpperCase()),
                  ],
                ),
              ),
              SizedBox(
                width: 20,
              ),
              text(caption: "X"),
              SizedBox(
                width: 20,
              ),
              Container(
                width: size.width / 4,
                child: Column(
                  children: <Widget>[
                    TextField(
                      controller: repsController,
                      keyboardType: TextInputType.number,
                      inputFormatters: [
                        WhitelistingTextInputFormatter.digitsOnly
                      ],
                    ),
                    SizedBox(height: 10),
                    text(caption: "reps".toUpperCase()),
                  ],
                ),
              ),
              SizedBox(width: 5.0),
              IconButton(
                icon: Icon(Icons.delete_forever),
                onPressed: delete,
              )
            ],
          ),
        ],
      ),
    );
  }
}

Ответы [ 2 ]

0 голосов
/ 08 ноября 2019

Я решил эту проблему, просто обновив SetModel при изменении текста в текстовом поле. Основными компонентами являются методы updatePounds и updateReps, а также методы onChanged в текстовых полях динамического виджета.

Я также позаботился о том, чтобы инициализировать контроллеры значениями, содержащимися вSetModel при создании динамического виджета.

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

void main() {
  runApp(MaterialApp(
    home: WorkoutStartScreen(),
  ));
}

class SetModel {
  final int id;
  int pounds;
  int reps;

  SetModel({
    this.id,
    this.pounds,
    this.reps,
  });

  void updatePounds(int pounds) {
    this.pounds = pounds;
  }

  void updateReps(int reps) {
    this.reps = reps;
  }
}

class WorkoutStartScreen extends StatefulWidget {
  static const String routeName = "workoutStart";
  @override
  _WorkoutStartScreenState createState() => _WorkoutStartScreenState();
}

class _WorkoutStartScreenState extends State<WorkoutStartScreen> {
  final List<SetModel> sets = [];

  void _addSet() {
    final id = sets.length;
    setState(() {
      sets.add(SetModel(id: id, pounds: 0, reps: 0));
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Workout tracker"),
        centerTitle: true,
      ),
      body: Container(
        child: Column(
          children: <Widget>[
            Expanded(
              child: ListView.builder(
                itemCount: sets.length,
                itemBuilder: (BuildContext context, int index) {
                  return DynamicWidget(
                    set: sets[index],
                    pos: index + 1,
                    delete: () {
                      setState(() {
                        sets.removeAt(index);
                      });
                    },
                  );
                },
              ),
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => _addSet(),
        child: Icon(Icons.add),
      ),
    );
  }
}

class DynamicWidget extends StatelessWidget {
  final TextEditingController poundsController = TextEditingController();
  final TextEditingController repsController = TextEditingController();

  final SetModel set;
  final int pos;
  final Function delete;

  DynamicWidget({
    Key key,
    @required this.set,
    @required this.pos,
    @required this.delete,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final Size size = MediaQuery.of(context).size;

    if (set.pounds != 0) {
      poundsController.text = set.pounds.toString();
    }

    if (set.reps != 0) {
      repsController.text = set.reps.toString();
    }

    return Container(
      child: Column(
        children: <Widget>[
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                child: Text(
                  "SET $pos",
                ),
              ),
              SizedBox(width: 20.0),
              Container(
                width: size.width / 4,
                child: Column(
                  children: <Widget>[
                    TextField(
                      controller: poundsController,
                      onChanged: (String pounds) {
                        set.updatePounds(int.parse(pounds));
                      },
                      keyboardType: TextInputType.number,
                      inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
                    ),
                    SizedBox(height: 10),
                    Text("pounds".toUpperCase()),
                  ],
                ),
              ),
              SizedBox(
                width: 20,
              ),
              Text("X"),
              SizedBox(
                width: 20,
              ),
              Container(
                width: size.width / 4,
                child: Column(
                  children: <Widget>[
                    TextField(
                      controller: repsController,
                      onChanged: (String reps) {
                        set.updateReps(int.parse(reps));
                      },
                      keyboardType: TextInputType.number,
                      inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],
                    ),
                    SizedBox(height: 10),
                    Text("reps".toUpperCase()),
                  ],
                ),
              ),
              SizedBox(width: 5.0),
              IconButton(
                icon: Icon(Icons.delete_forever),
                onPressed: delete,
              )
            ],
          ),
        ],
      ),
    );
  }
}

По сути, динамические виджеты перерисовываются каждый раз, когда вы вызываете setState из его родителя. Поскольку вы никогда не указывали динамическим виджетам сохранять что-либо, они перерисовываются с нуля. Это все еще происходит, за исключением того, что теперь мы даем им некоторую начальную информацию.

Здесь - видео о том, как оно работает.

0 голосов
/ 08 ноября 2019

Использовать контроллер!

TextEditingController password = new TextEditingController();

TextFormField(
                  validator: (value) {
                    if (value.isEmpty) {
                      return "Could not be empty";
                    }
                    return null;
                  },

                  enabled: !isLoading,
                  controller: password,
                  obscureText: hidePassword,
                  decoration: InputDecoration(
                    suffix: IconButton(icon: Icon((hidePassword)?Icons.remove_red_eye:Icons.cancel),onPressed: () => setState(() => hidePassword = !hidePassword),),
                      labelText: "PASSWORD",
                      border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(20))),
                  onFieldSubmitted: (String p) {
                    buttonPressed();
                  },
                ),

Затем получить его с помощью

var pass = username.text;

Очевидно, вы можете использовать массив контроллеров и затем получить их

...