ReorderableListView中的StatefulWidgets在重新排序列表时不会保持其状态。

问题描述 投票:0回答:1

在这里,我有一个修剪过的页面,它创建了一个 ReorderableListView,它的主体设置为两个 RecipeStepWidgetUniqueKeys集(我也曾尝试过用。ValueKeyObjectKey)

import 'package:flutter/material.dart';
import 'consts.dart';
import 'recipeStep.dart';
import 'recipeStepWidget.dart';

class NewRecipePage extends StatefulWidget {
  @override
  _NewRecipePageState createState() => _NewRecipePageState();
}

class _NewRecipePageState extends State<NewRecipePage> {
  final TextEditingController _nameController = TextEditingController();
  @override
  Widget build(BuildContext context) {
    List<RecipeStep> recipeSteps = [];

    List<RecipeStepWidget> stepWidgets = [
      RecipeStepWidget(key: UniqueKey()),
      RecipeStepWidget(key: UniqueKey())
    ];

    void _onReorder(int oldIndex, int newIndex) {
      setState(
        () {
          if (newIndex > oldIndex) {
            newIndex -= 1;
          }

          final RecipeStepWidget item = stepWidgets.removeAt(oldIndex);
          stepWidgets.insert(newIndex, item);
        },
      );
    }

    return Scaffold(
      appBar: AppBar(title: Text("New Recipe")),
      body: Column(
        children: <Widget>[
          Expanded(
            child: ReorderableListView(
              header: Text("Steps"),
              onReorder: _onReorder,
              children: stepWidgets,
            ),
          ),
        ],
      ),
    );
  }
}

RecipeStepWidget 类是(忽略包括)。

class RecipeStepWidget extends StatefulWidget {

  RecipeStepWidget({@required Key key}) : super(key: key);

  _RecipeStepWidgetState createState() => _RecipeStepWidgetState();

}

class _RecipeStepWidgetState extends State<RecipeStepWidget> {
  TextEditingController _controller = TextEditingController();
  TextEditingController _durationLowController = TextEditingController();
  TextEditingController _durationHighController = TextEditingController();
  bool concurrent = false;

  RecipeStep toRecipeStep() {
    return RecipeStep(
      text: _controller.text,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        TextField(
          controller: _controller,
          decoration: InputDecoration(hintText: "Step text"),
        ),
        Row(
          children: <Widget>[
            Text("Duration min: "),
            Container(
              width: 40.0,
              //height: 100.0,
              child: TextField(
                controller: _durationLowController,
                keyboardType: TextInputType.number,
                decoration: InputDecoration(hintText: "0"),
                onChanged: (String val) {
                  if (_durationHighController.text.isEmpty ||
                      int.parse(val) >
                          int.parse(_durationHighController.text)) {
                    _durationHighController.text = val;
                  }
                },
              ),
            ),
            Text(" max: "),
            Container(
              width: 40.0,
              //height: 100.0,
              child: TextField(
                controller: _durationHighController,
                keyboardType: TextInputType.number,
                decoration: InputDecoration(hintText: "0"),
              ),
            ),
          ],
        ),
        Row(
          children: <Widget>[
            Text("Start concurrently with previous step"),
            Checkbox(
                value: concurrent,
                onChanged: (bool val) => {
                      setState(() {
                        concurrent = val;
                      })
                    }),
          ],
        ),
      ],
    );
  }
}

当我编辑文本字段或复选框时,我在 RecipeStateWidgets 然后通过点击+拖动它们在列表中重新排序,小部件被重置为默认状态。

有人知道为什么会发生这种情况吗?我想我所要做的只是为了得到 ReorderableListView 以达到预期的工作效果,就是在它的每个子代上设置一个键。这样做不对吗?

谢谢!

flutter flutter-layout flutter-state
1个回答
0
投票

我想你可以像这样使用AutomaticKeepAliveClientMixin。

class _RecipeStepWidgetState extends State<RecipeStepWidget> with AutomaticKeepAliveClientMixin  {

  @override
  bool get wantKeepAlive => true;
© www.soinside.com 2019 - 2024. All rights reserved.