2

我正在制作一个问答应用程序来打发时间。

问题列表中有问题。下面的代码显示了每个问题。一个问题可以有多个选择,但只有一个答案。

我在每次输入 TextFormField 时遇到问题,光标会重置到开头。我怎样才能避免这种情况?我需要使用 setState 以便 Text Widget 实时更新。

class Question{
  int answer;
  List<Answer> answers;
}

class Answer{
  int index;
  String answer;
}

class EditQuestionWidget extends StatefulWidget {
  final List<Question> questions;
  final int index;

  EditQuestionWidget(this.questions, this.index);

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

class _EditQuestionWidgetState extends State<EditQuestionWidget> {
  @override
  Widget build(BuildContext context) {

    return Card( //For Each Question
      child: ExpansionTile(
        title: Text(widget.questions[widget.index].answer != null ? widget.questions[widget.index].answers[widget.questions[widget.index].answer].answer ?? 'Untitled Answer' : 'Untitled Answer'),
        children: <Widget>[

          ListView.builder( //For Each answer choice
            itemCount: widget.questions[widget.index].answers.length,
            itemBuilder: (context, i) {

              TextEditingController answerController = TextEditingController(text: widget.questions[widget.index].answers[i].answer);

              return Row(
                children: <Widget>[
                  Expanded(
                    child: RadioListTile( //Select Answer
                      value: widget.questions[widget.index].answers[i].index,
                      groupValue: widget.questions[widget.index].answer,
                      onChanged: (int value) => setState(() => widget.questions[widget.index].answer = value),
                      title: TextFormField( //change answer choice text
                        controller: answerController,
                        onChanged: (text) {
                          setState(() {widget.questions[widget.index].answers[i].answer = text;}); // The cursor returns to beginning after executing this.
                        },
                      ),
                    ),
                  ),
                  IconButton( //Remove Answer Function
                    onPressed: () {

                      //This method Works as intended.

                      if (widget.questions[widget.index].answers[i].index == widget.questions[widget.index].answer) widget.questions[widget.index].answer = null;
                      String answer = widget.questions[widget.index].answer != null ? widget.questions[widget.index].answers[widget.questions[widget.index].answer].answer : '';
                      widget.questions[widget.index].answers.remove(widget.questions[widget.index].answers[i]);

                      if (widget.questions[widget.index].answers.isEmpty) {
                        widget.questions[widget.index].answer = widget.questions[widget.index].answers.length;
                        widget.questions[widget.index].answers.add(new Answer(index: widget.questions[widget.index].answers.length));
                      }

                      for (int ii = 0; ii < widget.questions[widget.index].answers.length; ii++) {
                        widget.questions[widget.index].answers[ii].index = ii;
                        if (widget.questions[widget.index].answer != null && answer == widget.questions[widget.index].answers[ii].answer) widget.questions[widget.index].answer = ii;
                      }

                      setState(() {});
                    },
                  ),
                ],
              );

            },
          ),

        ],
      ),
    );

  }
}


4

1 回答 1

1

每次文本更改时,您都会更新answerController的值,并且当此更新发生时,光标会转到开头。

为了解决这个问题,您可以在构建器之外创建一个TextEditingControllers列表:

List<TextEditingController> controllers = [];

然后在创建新字段时将新控制器添加到列表中:

itemBuilder: (context, i) {
            if(controllers.length != widget.questions[widget.index].answers.length){
              controllers.add(TextEditingController());  //condition to prevent the creation of infinity Controllers
            }

最后将控制器传递给 TextField:

controller: controllers[i],
于 2020-05-10T15:32:48.340 回答