在步进器中保持状态

时间:2020-01-08 08:21:57

标签: flutter

我的步进器有多个步骤。在每个步骤之间移动时如何保持步骤状态?

我曾尝试添加AutomaticKeepAliveClientMixin,但它仍不保持状态:

class _MyHomePageState extends State<MyHomePage> with AutomaticKeepAliveClientMixin<MyHomePage> {
  int currentStep = 0;
  List<Step> stepList = [
    Step(
      title: Text("Page A"),
      content: Column(
        children: <Widget>[
          Text("Page A"),
          TextField(
            decoration: InputDecoration(
              border: InputBorder.none,
              hintText: "Enter anything"
            ),
          ),
        ],
      )
    ),
    Step(
      title: Text("Page B"),
      content: Text("Page B")
    ),
    Step(
      title: Text("Page C"),
      content: Text("Page C")
    ),
    Step(
      title: Text("Page D"),
      content: Text("Page D")
    ),
    Step(
      title: Text("Page E"),
      content: Text("Page ")
    ),
  ];

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
      body: Stepper(
        steps: stepList,
        type: StepperType.horizontal,
        currentStep: currentStep,
        onStepContinue: nextStep,
        onStepCancel: cancelStep,
      ),
    );
  }

  void nextStep(){
    setState(() {
      if(currentStep < stepList.length - 1)
        currentStep++;
    });
  }

  void cancelStep(){
    setState(() {
      if(currentStep > 0)
      currentStep--;
    });
  }

  @override
  bool get wantKeepAlive => true;
}

如果我在文本字段中添加了任何内容,请导航至PageB,然后导航至PageA,该文本字段将重置为空白。

如何保持每个步骤的“页面”的状态?

编辑: 可能应该早些披露。我有5个步骤,每个步骤包含8-12个字段,包括文本字段,复选框,下拉列表等。这是一个多步骤表单。我知道您可以创建一个类级别的TextFieldController来拥有一个“全局”变量,以在Step中跟踪TextField的状态,但这意味着我需要约50个类级别的变量,代码看起来太复杂了。这就是为什么我使用AutomaticKeepAliveClientMixin,但是它不起作用。有更好的方法来解决这个问题吗?

4 个答案:

答案 0 :(得分:1)

正在发生的事情是,当您从另一个TextField导航到Step时,它正在重建,因此值正在重置。

解决方案:

  1. List<Step>转换为get的{​​{1}}就像List<Step>
  2. 这样做的原因是使您的列表能够访问全局变量。
  3. 创建一个List<Step> get stepList => [作为全局变量:TextEditingController
  4. 将该控制器交给您的TextEditingController textEditingController = TextEditingController();,如下所示:

    TextField

现在将要发生的是,当您拥有 TextField( controller: textEditingController, decoration: InputDecoration( border: InputBorder.none, hintText: "Enter anything" ), ), 时,无论何时TextEditingController进行重建,只要您在TextField之间进行切换,它将使用控制器来获取值。您的Step值不会重置。

我已经编辑了您的代码,以下是具有上述更改的代码:

TextField

希望对您有所帮助,如有任何疑问,请发表评论。 如果此答案对您有帮助,请接受并对其进行投票。

答案 1 :(得分:0)

这是Stepper Widget的示例实现。您不必担心保持状态:

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  int currentStep = 0;

  List<Step> stepList = [];

  @override
  void initState() {
    stepList = [
      Step(
        title: Text('Step 1 title'),
        content: Text('Step 1 content'),
        isActive: currentStep == 0,
      ),
      Step(
        title: Text('Step 2 title'),
        content: Text('Step 2 content'),
        isActive: currentStep == 1,
      ),
      Step(
        title: Text('Step 3 title'),
        content: Text('Step 3 content'),
        isActive: currentStep == 2,
      ),
    ];
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('StackOverflow'),
      ),
      resizeToAvoidBottomInset: false,
      body: Center(
        child: Column(
          children: <Widget>[
            Text('test'),
            Stepper(
              currentStep: currentStep,
              onStepContinue: nextStep,
              onStepCancel: prevStep,
              steps: stepList,
            )
          ],
        ),
      )
    );
  }

  void nextStep(){
    setState(() {
      if(currentStep < stepList.length - 1)
        currentStep++;
    });
  }

  void prevStep(){
    setState(() {
      if(currentStep > 0)
       currentStep--;
    });
  }
}

答案 2 :(得分:0)

您可以在下面复制粘贴运行完整代码
您可以使用TextEditingController()

代码段

 TextEditingController _pageA = TextEditingController();

 Step(
        title: Text("Page A"),
        content: Column(
          children: <Widget>[
            Text("Page A"),
            TextField(
              controller: _pageA,

工作演示

enter image description here

完整代码

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController _pageA = TextEditingController();
  int currentStep = 0;
  List<Step> stepList;

  @override
  void initState() {
    super.initState();
    stepList = [
      Step(
        title: Text("Page A"),
        content: Column(
          children: <Widget>[
            Text("Page A"),
            TextField(
              controller: _pageA,
              decoration: InputDecoration(
                  border: InputBorder.none, hintText: "Enter anything"),
            ),
          ],
        ),
        state: StepState.indexed,
      ),
      Step(title: Text("Page B"), content: Text("Page B")),
      Step(title: Text("Page C"), content: Text("Page C")),
    ];
  }

  @override
  void dispose() {
    _pageA.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stepper(
          steps: stepList,
          type: StepperType.horizontal,
          currentStep: currentStep,
          onStepContinue: nextStep,
          onStepCancel: cancelStep,
          onStepTapped: (step) {
            setState(() {
              currentStep = step;
            });
          }),
    );
  }

  void nextStep() {
    setState(() {
      if (currentStep < stepList.length - 1) currentStep++;
    });
  }

  void cancelStep() {
    setState(() {
      if (currentStep > 0) currentStep--;
    });
  }
}

答案 3 :(得分:0)

好吧,您必须将 AutomaticKeepAliveClientMixin 与具有步进器的实际小部件一起使用,而不是您的步骤小部件。 这样,当您在屏幕之间导航时,每个步骤都会保留