Do somthings

DoSomthings logo
Creating a multi-step form in Flutter gif(Dosomthings.com)

In this blog post, we will walk you through the process of creating a multi-step form in Flutter. A multi-step form is a user interface component that breaks down a complex form into smaller, more manageable steps, enhancing the user experience and improving data collection. By following this step-by-step guide, you’ll be able to implement a multi-step form in your Flutter application.

In the realm of web development and user experience design, multi-step forms have emerged as powerful tools to enhance user engagement and improve conversion rates. By breaking down complex forms into smaller, more manageable sections, multi-step forms guide users through a series of well-structured steps, ensuring a smoother and more intuitive experience. In this post, we’ll explore a real-life example of a multi-step form and delve into its benefits and best practices. example: A Travel Booking Website, an e-commerce site, delivering your order, registration form, etc.

Step 1: Set Up a New Flutter Project

Before we dive into creating the multi-step form, let’s start by setting up a new Flutter project. Create and open your Flutter project Use the Flutter CLI or your preferred IDE to create a new project template I am using Android Studio I am comfortable with this.

Step 2: Add Dependencies

To build our multi-step form, we’ll need to add some dependencies to our pubspec.yaml file. Open the file and add the following dependencies:

In this project, we use im_stepper 1.0.1+1 package for a better and easy way to archive the layout & functionality.

open your pubsec.yaml file and add this line and click Pub get button

dependencies:
  im_stepper: ^1.0.1+1

And one more package for font style is Google Font and the package name is google_fonts 4.0.4 and it is easy to implement like this

dependencies:
  google_fonts: ^4.0.4

Step 3: Design the User Interface

I am creating a separate folder and class for storing color values it is good practice for coding you can also using these techniques for improve your coding style

creating one folder inside of lib folder like this structure; lib -> AppColors -> project_color.dart.

and inside of project_color.dart file code in blow

import 'dart:ui';
import 'package:flutter/material.dart';

class ProjectColors{

  static const Color transparent = Color(0x00000000);
  static const Color theamColor = Color(0xFF2ab7ca);
  //static const Color backgroundColor = Color(0xFFfe8a71);
  static const Color backgroundColor = Color(0xFFffe801);
  //static const Color textColor = Color(0xFF010127);
  static const Color textColor = Color(0xFF4611a6);
  static const Color appBg = Color(0xFF319964);

}

Now, let’s design the user interface for our multi-step form. Create a new Flutter widget for each step in your form. Each step widget should represent a single page/screen and contain the relevant form fields.

open your main.dart file and place this code

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

void main() {
  runApp(IconStepperDemo());
}

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

class _IconStepperDemo extends State<IconStepperDemo> {
  // THE FOLLOWING TWO VARIABLES ARE REQUIRED TO CONTROL THE STEPPER.
  int activeStep = 2; // Initial step set to 5.

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: Text('IconStepper Example'),
          centerTitle: true,
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              IconStepper(
                icons: [
                  Icon(Icons.supervised_user_circle),
                  Icon(Icons.flag),
                  Icon(Icons.access_alarm),
                  Icon(Icons.safety_check),
                  Icon(Icons.face),
                  Icon(Icons.ac_unit),
                  Icon(Icons.satellite_rounded),
                ],

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

                // This ensures step-tapping updates the activeStep.
                onStepReached: (index) {
                  setState(() {
                    activeStep = index;
                  });
                },
              ),
              header(),
              Expanded(
                child: FittedBox(
                  child: Center(
                    child: Text('$activeStep'),
                  ),
                ),
              ),
              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'),
    );
  }

  /// 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('Prev'),
    );
  }

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

  // Returns the header text based on the activeStep.
  String headerText() {
    switch (activeStep) {
      case 1:
        return 'Preface';

      case 2:
        return 'Table of Contents';

      case 3:
        return 'About the Author';

      case 4:
        return 'Publisher Information';

      case 5:
        return 'Reviews';

      case 6:
        return 'Chapters #1';

      default:
        return 'Introduction';
    }
  }
}
Creating a multi-step form in Flutter(Dosomthings.com)
Creating a multi-step form in Flutter(Dosomthings.com)
Creating a multi-step form in Flutter(Dosomthings.com)

If you want an attractive and creative design like in the top gif then you try this code for entertainment or create something different, so use this code.

For multi-step form in Flutter

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:testing/AppColors/project_color.dart';
import 'package:im_stepper/stepper.dart';

void main() {
  runApp(
      MaterialApp(
        home:   IconStepperDemo(),
      )

  );
}

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

class _IconStepperDemo extends State<IconStepperDemo> {


  // THE FOLLOWING TWO VARIABLES ARE REQUIRED TO CONTROL THE STEPPER.
  int activeStep = 2; // Initial step set to 5.
  int upperBound = 6; // upperBound MUST BE total number of icons minus 1.
  bool beforeIcon = false;

  final String Rule1 = "Under 10 minutes \nTournament";
  final String Rule2 = "15 secend per move";
  final String Rule3 = "No need to roll a 6\nto start the game";
  final String Rule4 = "1 box moved =\n1 point earn";
  final String Rule5 = "Point get deduted\nwhen your token is cut";
  final String Rule6 = "Get extra 56 points\non taking each other token";
  final String Rule7 = "Skipping thrice\nwill end the game";


  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: Text('IconStepper Example'),
          centerTitle: true,
        ),
        body: Padding(
          padding: EdgeInsets.all(10.0),
          child:  GestureDetector(
            onTap: () {
              showModalBottomSheet(

                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.only(
                        topLeft: const Radius.circular(25.0),
                        topRight: const Radius.circular(25.0)),
                  ),
                  backgroundColor: Color(0xFFE4E4E4),
                  context: context,
                  isScrollControlled: true,
                  builder: (context) {
                    return StatefulBuilder(

                        builder: (BuildContext context, StateSetter setState /*You can rename this!*/) {

                          return FractionallySizedBox(
                              heightFactor: 0.6,
                              child: buildSheetInfo(context,setState)
                          );

                        }


                    );

                  }
              );
            },
            child: Center(
              child: Container(
                  child: CircleAvatar(
                    backgroundImage: NetworkImage('https://studio.code.org/media?u=https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2FLn2d9ocIIBvRYIFY5R%2Fsource.gif'),
                    radius: 50,
                    backgroundColor: Colors.transparent,
                  )
              ),
            )

          ),
        ),


      ),
    );
  }


  //For help info
  Widget buildSheetInfo(context, setState) {


    return Column(
      children: <Widget>[

        Align(
          alignment: Alignment.topRight,
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: new IconButton(
                icon: Icon(
                  Icons.cancel,
                  color: Colors.black,
                  size: 30,
                ),
                onPressed: () {
                  Navigator.pop(context);
                }),
          ),
        ),

        ImageStepper(
          images: [
            NetworkImage('https://i.pinimg.com/originals/01/28/46/0128468e98f1312cb40ef96218f4f6a5.gif'),
            NetworkImage('https://media2.giphy.com/media/YRyvFrNopIIKNSyQ0a/200w.gif?cid=82a1493b2vc4t7gkpwh3iv7q03zevkvwse1lfyy4mdjl8jbh&ep=v1_gifs_related&rid=200w.gif&ct=g'),
            NetworkImage('https://media.tenor.com/GS3glUNc6-YAAAAC/dice.gif'),
            NetworkImage('https://thumbs.gfycat.com/LightheartedDimpledBasil-size_restricted.gif'),
            NetworkImage('https://i.pinimg.com/originals/8f/06/04/8f0604aedc34d33d2f41113c312a588d.gif'),
            NetworkImage('https://i.pinimg.com/originals/63/89/fa/6389fa22ed7653c40570c98b03764afc.gif'),
            NetworkImage('https://1b-f.s3.eu-west-1.amazonaws.com/a/2748-AA4C48F6-B253-422A-8B0C-11DD24DC23FE-0-1517782210.gif'),

          ],

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

          // This ensures step-tapping updates the activeStep.
          onStepReached: (index) {
            setState(() {
              activeStep = index;
            });
          },
        ),

        SizedBox(height: 20,),

        Text(
          "LEARN TO PLAY\nSTART WINNING",
          style: GoogleFonts.lato(
              fontSize: 20,
              fontWeight: FontWeight.bold,
              color: ProjectColors.textColor,
              fontStyle: FontStyle.italic),
          textAlign: TextAlign.center,
        ),

        SizedBox(
          height: 10,
        ),

        Container(
          margin: EdgeInsets.all(10.0),
          decoration: const BoxDecoration(
              borderRadius: BorderRadius.all(Radius.circular(20.0)),
              color: Colors.white),
          child: Center(
            child: Padding(
              padding: const EdgeInsets.all(10.0),
              child: Column(
                children: <Widget>[

                  Padding(
                    padding: EdgeInsets.all(10.0),
                    child: Divider(),
                  ),

                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[

                      Text(headerText(),
                          style: GoogleFonts.lato(
                              fontSize: 16,
                              fontWeight: FontWeight.bold,
                              color: ProjectColors.textColor)),

                      CircleAvatar(
                        radius: 25,
                        backgroundImage:
                        NetworkImage(headerIcon()),

                        // backgroundColor: Colors.grey.shade400,
                      ),
                    ],
                  ),

                  SizedBox(
                    height: 10,
                  ),

                  Padding(
                    padding: EdgeInsets.all(10.0),
                    child: Divider(),
                  ),

                ],
              ),
            ),
          ),
        ),

        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            previousButton(setState),
            nextButton(setState),
          ],
        ),

      ],
    );
  }


  //For image icon
  String headerIcon() {
    switch (activeStep) {

      case 0:
        return  'https://i.pinimg.com/originals/01/28/46/0128468e98f1312cb40ef96218f4f6a5.gif';

      case 1:
        return 'https://media2.giphy.com/media/YRyvFrNopIIKNSyQ0a/200w.gif?cid=82a1493b2vc4t7gkpwh3iv7q03zevkvwse1lfyy4mdjl8jbh&ep=v1_gifs_related&rid=200w.gif&ct=g';

      case 2:
        return 'https://media.tenor.com/GS3glUNc6-YAAAAC/dice.gif';

      case 3:
        return 'https://thumbs.gfycat.com/LightheartedDimpledBasil-size_restricted.gif';

      case 4:
        return 'https://i.pinimg.com/originals/8f/06/04/8f0604aedc34d33d2f41113c312a588d.gif';

      case 5:
        return 'https://i.pinimg.com/originals/63/89/fa/6389fa22ed7653c40570c98b03764afc.gif';

      case 6:
        return 'https://1b-f.s3.eu-west-1.amazonaws.com/a/2748-AA4C48F6-B253-422A-8B0C-11DD24DC23FE-0-1517782210.gif';

      default:
        return "";
    }
  }

  // Returns the header text based on the active Step...
  String headerText() {
    switch (activeStep) {
      case 0:
        return Rule1;

      case 1:
        return Rule2;

      case 2:
        return Rule3;

      case 3:
        return Rule4;

      case 4:
        return Rule5;

      case 5:
        return Rule6;

      case 6:
        return Rule7;

      default:
        return "";
    }
  }

  /// Returns the next button.
  Widget nextButton(setState) {
    return Container(
      margin: EdgeInsets.only(right: 20),
      child: ElevatedButton(
        onPressed: () async {
          if (activeStep < upperBound) {
            setState(() {
              activeStep++;
              beforeIcon = true;

            });
          }
        },
        child: Padding(
          padding: const EdgeInsets.only(left: 20,right: 20),
          child: Text(
            "Next",
            style: GoogleFonts.lato(
              fontSize: 14,
              fontWeight: FontWeight.bold,
              color: ProjectColors.textColor,
            ),
          ),
        ),
        style: ElevatedButton.styleFrom(
          backgroundColor: ProjectColors.backgroundColor,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(20.0),
          ),
        ),
      ),
    );

  }

  /// Returns the previous button.
  Widget previousButton(setState) {
    return Visibility(
      visible: beforeIcon,
      child: Container(
        margin: EdgeInsets.only(left: 20),
        child: InkWell(
          onTap: () {
            // 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--;
                beforeIcon = true;
              });
            }
          },
          child: Icon(Icons.navigate_before_outlined,color: Colors.black,size: 40,),
        ),
      ),
    );
  }


}

Output

Creating a multi-step form in Flutter(Dosomthings.com)
Creating a multi-step form in Flutter(Dosomthings.com)
Creating a multi-step form in Flutter(Dosomthings.com)

Conclusion

Congratulations! You have successfully created a multi-step form in Flutter. By breaking down complex forms into smaller steps, you can enhance the user experience and improve data collection in your Flutter application. Experiment with different UI designs, validators, and data handling techniques to further customize and optimize your multi-step form. Happy coding!

if you are interested in this type of new and attractive coding stuff then you follow my site Click here.

BarCode scannerBarcode scanner / QR Code Scanner in Flutter.

Flip/Rotate 3D –  Flip/Rotate 3D Image Object By Drag Gestures Flipping Card.

scratch cardHow to create scratch card in flutter using a scratcher package.