Search code examples
dartflutterstepper

Flutter: Stepper onStepContinue not firing


Can you tell me what's wrong in my code?

Widget _createProfileStepper() {
int currentStep = 0;

List<Step> createAccSteps = [
  new Step(
    title: Container(),
    content: new Text('This is the first step.'),
    isActive: currentStep >= 0,
    state: currentStep >= 0 ? StepState.editing : StepState.disabled,
  ),
  new Step(
    title: Container(),
    content: new Text('This is the second step.'),
    isActive: currentStep >= 0,
    state: currentStep >= 1 ? StepState.editing : StepState.disabled,
  ),
  new Step(
    title: Container(),
    content: new Text('This is the third step.'),
    isActive: currentStep >= 0,
    state: currentStep >= 2 ? StepState.editing : StepState.disabled,
  ),
  new Step(
    title: Container(),
    content: new Text('This is the second step.'),
    isActive: currentStep >= 0,
    state: currentStep >= 3 ? StepState.editing : StepState.disabled,
  ),
  new Step(
    title: Container(),
    content: new Text('This is the third step.'),
    isActive: currentStep >= 0,
    state: currentStep >= 4 ? StepState.editing : StepState.disabled,
  ),
];

return Scaffold(
  appBar: AppBar(
    title: Text("Create Profile"),
  ),
  body: Stepper(
    type: StepperType.horizontal,
    currentStep: currentStep,
    onStepTapped: (step) {
      setState(() {
        currentStep = step;
      });
    },
    onStepContinue: () {
      setState(() {
        if (currentStep < createAccSteps.length - 1) {
          currentStep = currentStep + 1;
        } else {}
      });
    },
    onStepCancel: () {
      setState(() {
        if(currentStep > 0){
          currentStep = currentStep - 1;
        }
        else {
          currentStep = 0;
        }
      });
    },
    steps: createAccSteps,
  ),
);
}

I followed all examples for Flutter's stepper but still no luck. I can tap the continue button but it is not moving to another step. Did I forget something? I created a Stateful Widget class then a button would take me to call this _createProfileStepper(). Thanks.


Solution

  • By having the entire code in _createProfileStepper() the widget becomes stateless even if it is used in a stateful widget. This is because whenever the build method of the stateful widget is re-running, it will call _createProfileStepper() which will cause the entire stepper widget to reinitialize i.e re-create the stepper, and thus the continue does not work.

    Why not create a stateful widget for the step alone and use that widget instead of the one you're getting from _createProfileStepper(). For example:

    class _SimpleWidgetState extends State<SimpleWidget> {
      int currentStep = 0;
    
      List<Step> steps = [
        Step(
            title: Text("Step One"),
            content: Text("This is the first step"),
            isActive: true
        ),
        Step(
          title: Text("Step Two"),
          content: Text("This is the second step"),
          isActive: true,
        ),
        Step(
          title: Text("Step Three"),
          content: Text("This is the third step"),
          isActive: true,
        ),
        Step(
          title: Text("Step Four"),
          content: Text("This is the fourth step"),
          isActive: false,
        ),
      ];
    
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Stepper(
            steps: steps,
            currentStep: currentStep,
            type: StepperType.vertical,
            onStepTapped: (step) {
              setState(() {
                currentStep = step;
                print(step);
              });
            },
            onStepCancel: () {
              setState(() {
                currentStep > 0 ? currentStep -= 1 : currentStep = 0;
              });
            },
            onStepContinue: () {
              setState(() {
                currentStep < steps.length - 1 ? currentStep += 1 : currentStep = 0;
              });
            },
          ),
        );
      }
    }
    
    class SimpleWidget extends StatefulWidget {
      @override
      _SimpleWidgetState createState() {
        // TODO: implement createState
        return _SimpleWidgetState();
      }
    }
    

    Then use SimpleWidget() where you would _createProfileStepper()

    Secondly As regards your question about your list accessing currentStep is because only static members can be used for initialization