简体   繁体   English

Flutter 维护并记住步进器之间的状态

[英]Flutter maintain and remember state between steppers

I am trying to implement a daily task stepper and used im_stepper library.我正在尝试实现一个日常任务步进器并使用im_stepper库。 The library works well and does what it needs to on the tin.该库运行良好,并在罐头上做它需要做的事情。

I am a bit stuck on one of the aspects, where I need check boxes and it needs to maintain the state of the checkboxes.我在其中一个方面有点卡住了,我需要复选框并且需要维护复选框的状态。

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:im_stepper/stepper.dart';

class IconStepperDemo extends StatefulWidget {
  @override
  _IconStepperDemo createState() => _IconStepperDemo();
}

class _IconStepperDemo extends State<IconStepperDemo> {
// THE FOLLOWING TWO VARIABLES ARE REQUIRED TO CONTROL THE STEPPER.

// Initial step set to 5.
  int activeStep = 0;

// upperBound MUST BE total number of icons minus 1.
  int upperBound = 13;

//Logic for checkboxs. Needs a revist.
  bool checkbox1 = false;
  bool checkbox2 = false;
  bool checkbox3 = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          leading: IconButton(
            icon: BackButtonIcon(),
            onPressed: () => Navigator.of(context).pop(),
          ),
          brightness: Brightness.light,
          elevation: 10,
          centerTitle: true,
          title: Text("Daily Task List",
              style: TextStyle(
                color: Colors.white,
                decorationStyle: TextDecorationStyle.double,
              )),
          backgroundColor: PRIMARY,
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              IconStepper(
                icons: [
                  Icon(Icons.task),
                  Icon(Icons.alarm),
                  Icon(Icons.flag),
                ],

                // activeStep property set to activeStep variable defined above.
                activeStep: activeStep,

                // This ensures step-tapping updates the activeStep.
                onStepReached: (index) {
                  setState(() {
                    activeStep = index;
                  });
                },
              ),
              spaceHeightWidget(sizeParam: 30),
              header(),
              spaceHeightWidget(sizeParam: 20),
              task1(),
              spaceHeightWidget(sizeParam: 20),
              task2(),
              spaceHeightWidget(sizeParam: 20),
              task3(),
              spaceHeightWidget(sizeParam: 20),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  previousButton(),
                  nextButton(),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }

  /// Returns the next button.
  Widget nextButton() {
    return ElevatedButton(
      onPressed: () {
        // Increment activeStep, when the next button is tapped. However, check for upper bound.
        if (activeStep < upperBound) {
          setState(() {
            activeStep++;
          });
        }
      },
      child: Text('Next'),
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.all<Color>(PRIMARY),
      ),
    );
  }

  /// Returns the previous button.
  Widget previousButton() {
    return ElevatedButton(
      onPressed: () {
        // Decrement activeStep, when the previous button is tapped. However, check for lower bound i.e., must be greater than 0.
        if (activeStep > 0) {
          setState(() {
            activeStep--;
          });
        }
      },
      child: Text('Previous'),
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.all<Color>(PRIMARY),
      ),
    );
  }

  /// Returns the header wrapping the header text.
  Widget header() {
    return Container(
      decoration: BoxDecoration(
        color: PRIMARY,
        borderRadius: BorderRadius.circular(5),
      ),
      child: Row(
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text(
              headerText(),
              textAlign: TextAlign.center,
              style: TextStyle(
                color: Colors.white,
                fontSize: 20,
              ),
            ),
          ),
        ],
      ),
    );
  }

  // Returns the header text based on the activeStep.
  String headerText() {
    switch (activeStep) {
      case 1:
        return 'Day $activeStep: Readings & Learning';

      case 2:
        return 'Day $activeStep: Understand your day';

      case 3:
        return 'Day $activeStep: Why is mindfulness important';

      default:
        return 'Day $activeStep: Lets get started';
    }
  }

  String taskText1() {
    switch (activeStep) {
      case 1:
        return 'Take morning reading';

      case 2:
        return 'Take morning reading';

      case 3:
        return 'Take morning reading';

      default:
        return 'Watch Video';
    }
  }

  String taskText2() {
    switch (activeStep) {
      case 1:
        return 'Watch breathing video';

      case 2:
        return 'Watch What is Mindfullness? Video';

      case 3:
        return 'Watch Why is Mindfulness Important Video';

      default:
        return 'Schedule reminders for morning exercise';
    }
  }

  String taskText3() {
    switch (activeStep) {
      case 1:
        return 'Practice a 2-minute breathing exercise';

      case 2:
        return 'Practice a 4-minute breathing exercise';

      case 3:
        return 'Practice a 6-minute breathing exercise';

      default:
        return 'Take your first morning jog';
    }
  }

  Widget task1() {
    return Container(
      //  decoration: BoxDecoration(border: Border.all(color: PRIMARY)),
      child: CheckboxListTile(
        title: Text(taskText1()),
        value: checkbox1,
        onChanged: (value) => setState(() => this.checkbox1 = value),
      ),
    );
  }

  Widget task2() {
    return Container(
      //  decoration: BoxDecoration(border: Border.all(color: PRIMARY)),
      child: CheckboxListTile(
        title: Text(taskText2()),
        value: checkbox2,
        onChanged: (value) => setState(() => this.checkbox2 = value),
      ),
    );
  }

  Widget task3() {
    return Container(
      //  decoration: BoxDecoration(border: Border.all(color: PRIMARY)),
      child: CheckboxListTile(
        title: Text(taskText3()),
        value: checkbox3,
        onChanged: (value) => setState(() => this.checkbox3 = value),
      ),
    );
  }
}

Gif shows currently what is happening with the checkboxes. Gif显示当前复选框发生的情况。

The questions are:问题是:

  1. Is the code extremely basic as I used the example provided and added the checkboxes?当我使用提供的示例并添加复选框时,代码是否非常基本?
  2. Do I need to implement a DB here to remember the tasks completed by the users?我需要在这里实现一个数据库来记住用户完成的任务吗? As it will be a one-off thing as an onboarding task for the app因为作为应用程序的入职任务,这将是一次性的

Any suggestions would be appreciated.任何建议,将不胜感激。

Your code currently doesn't make a distinction between 2 checkboxes in the same position on different pages.您的代码目前没有区分不同页面上相同位置的 2 个复选框。 One possible solution would be to have a 2d array in your state:一种可能的解决方案是在您的状态下使用二维数组:

final checkboxPages = [
  [false, false, false],  // page 1
  [false, false, false],  // page 2
  [false, false, false],  // page 3
];

// this would replace the 3 checkbox bools

Here we have a list containing 3 smaller lists, each representing a page.这里我们有一个包含 3 个较小列表的列表,每个列表代表一个页面。 Then if you wanted to read/write the state for a particular box on a page, you could have:然后,如果您想读取/写入页面上特定框的状态,您可以:

checkboxPages[1][0] = true;  // second page, first checkbox
var selected = checkboxPages[0][2];  // first page, third checkbox

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM