Flutter: How to Build Intro Slider for your App

Watch the video tutorial:

The steps involved are:

  • Create a new Flutter project
  • Create a new stateful widget MyApp in main.dart
  • Create a new stateful widget IntroSlider
  • Create a new Widget EachPage
  • Create an Indicator widget for the PageView

Create a new Futter project, remove the existing code of the MyApp widget, and create a new stateless widget MyApp.

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

Create a new widget IntroSlider in a new file intro_slider.dart.

class IntroSlider extends StatefulWidget {
  @override
  _IntroSliderState createState() => _IntroSliderState();
}

class _IntroSliderState extends State<IntroSlider> {

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

Update MyApp to return IntroSlider

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: IntroSlider());
  }
}

Add PageView to IntroSlider . Also add a PageController, arrays for messages, and images to be displayed on each page and variables for total number of pages and to hold the index of the current page.

Also include the image assets.

And we are returning a widget called EachPage from the itemBuider of the PageView.buider which we have not created yet.


class IntroSlider extends StatefulWidget {
  @override
  _IntroSliderState createState() => _IntroSliderState();
}

class _IntroSliderState extends State<IntroSlider> {

  //Controller for the PageView
  PageController controller= PageController();

  final messages = ["First Screen", "Second Screen", "Third Screen"];
  final images = [
    'assets/images/slider1.jpg',
    'assets/images/slider2.jpg',
    'assets/images/slider3.jpg'
  ];

  int numberOfPages=3;
  int currentPage=0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView.builder(
        controller: controller,
        itemCount: numberOfPages,
        itemBuilder: (BuildContext context, int index) {
          return EachPage(messages[index], images[index]);
        },
      ),
    );
  }
}

Now let’s create the EachPage widget for displaying a page of the PageView. We shall pass the message and image resource for each page while calling this widget from IntroSlider widget.

class EachPage extends StatelessWidget {

  final String message;
  final String image;

  EachPage(this.message, this.image);

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: Container(
        color: Colors.amberAccent,
        child: Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Image.asset(
                image,
                fit: BoxFit.scaleDown,
                width: 200,
                height: 200,),
              Text(message)
            ],
          ),
        ),
      ),
    );
  }
}

Now if we run the app we can that we have a beautiful slider of three pages each page displays an image and a text.

Next, we shall add a page indicator and a “Skip” button. The “Skip” button will be replaced by a “Login” button if the current page is the last page of the slider. On clicking the skip button it will jump directly to the last page of the PageView.

These above-mentioned widgets should overlap with the PageView, thus we’ll enclose the PageView inside a Stack widget.

Following steps are the next:

  • Wrap PageView inside a Stack widget
  • Add onPageChanged listener to the PageView and change the value of currentPage there
  • Add an Align widget (aligned to bottom) as the second child of the Stack. This will contain the page indicator and the buttons.

class IntroSlider extends StatefulWidget {
  @override
  _IntroSliderState createState() => _IntroSliderState();
}

class _IntroSliderState extends State<IntroSlider> {

  //Controller for the PageView
  PageController controller= PageController();

  final messages = ["First Screen", "Second Screen", "Third Screen"];
  final images = [
    'assets/images/slider1.jpg',
    'assets/images/slider2.jpg',
    'assets/images/slider3.jpg'
  ];

  int numberOfPages=3;
  int currentPage=0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: <Widget>[PageView.builder(
          controller: controller,
          onPageChanged: (index){
            setState(() {
              currentPage=index;
            });
          },
          itemCount: numberOfPages,
          itemBuilder: (BuildContext context, int index) {
            return EachPage(messages[index], images[index]);
          },
        ),
          Align(
            alignment: Alignment.bottomCenter,
            child: Container(
              height: 50,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: <Widget>[
                  Flexible(child: Container()),
                  Flexible(
                    child: Indicator(
                      controller: controller,
                    ),
                  ),
                  Flexible(

                    child: (currentPage==numberOfPages-1)?
                    GestureDetector(
                        onTap: (){},
                        child: Center(
                            child: RaisedButton(
                              onPressed: () {},
                              child: Text("Login",style: TextStyle(fontWeight: FontWeight.bold)),
                            ))):
                    GestureDetector(
                        onTap: (){
                          controller.jumpToPage(numberOfPages-1);
                        },
                        child: Center(child: Text("Skip",style: TextStyle(fontWeight: FontWeight.bold),))),
                  )
                ],),
            ),
          )
        ],
      ),
    );
  }
}

Now you might already have noticed that we have used a new widget named Indicator in the code above but we haven’t created it yet. So let us create the Indicator widget to display the page indicator.

Following are the steps to create a simple Indicator widget:

  • Create an AnimatedWidget named Indicator in a new file
  • We will pass our PageController from IntroSlider to this widget which will be passed to the superclass as a value for the property ‘listenable’, we’ll also pass the number of pages.
  • From the build() method return a list of n number of containers; where n is the number of pages and each container will represent a dot indicator.
  • Create the indicator dots using _createIndicator(index) method. If this index is equal to the index of the current page we shall enlarge the dot a little.

class Indicator extends AnimatedWidget {

  final PageController controller;
  final int pageCount;
  const Indicator({this.controller,this.pageCount}) : super(listenable: controller);

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 50,
      child: Row(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[ListView.builder(
            shrinkWrap: true,
            itemCount: pageCount,
            scrollDirection: Axis.horizontal,
            itemBuilder: (context,index){
              return _createIndicator(index);
            })],
      ),
    );
  }
  Widget _createIndicator(index) {
    double w=10;
    double h=10;
    MaterialColor color=Colors.grey;

    if(controller.page==index)
    {
      color=Colors.blueGrey;
      h=13;
      w=13;
    }

    return Container(
      height: 26,
      width: 26,
      child: Center(
        child: AnimatedContainer(
          margin: EdgeInsets.all(5),
          color: color,
          width: w,
          height: h,
          duration: Duration(milliseconds: 300),
        ),
      ),
    );
  }
}

Now if we run the app we will have a slider with the page indicator and the skip/login button.

The complete source code for the tutorial can be found on GitHub
https://github.com/gitanjal/flutter_examples/tree/master/flutter_intro_slider

Leave a Reply

Your email address will not be published.