Automatically changing pages using the PageView widget

Why PageView?

PageView widget can be used in a lot of situations, one such situation is when the user starts the app for the first time. If you want to provide your user with some information, instructions, or some tips and then redirect him/her to the actual sign-in/sign-up screen then this is for you!

  1. Create a new flutter project

Use Android Studio or your terminal to create a new flutter project and run your project in any IDE like Android Studio or Visual Studio Code and delete all the default code written in the project.

2. Setting up our files

Here, I create a package named pages in which I create 3 stateless widgets named Page1.dart, Page2.dart, and Page3.dart for the page view, then I created a package named screens which contains a stateful widget for the PageView screen called PageView.dart and a stateless widget for the Sign In screen which is named SignIn.dart.

Here is how my files look like

3. Coding our screens

  1. Coding Page1, Page2 and Page3
import 'package:flutter/material.dart';

class Page1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
),
body: Center(
child: Text(
'Page 1',
style: TextStyle(
color: Colors.black,
fontSize: 20
),
),
),
);
}
}

Similarly coding the rest 2 screens with classes named as Page2.dart and Page3.dart

2. Coding the PageView screen

import 'package:medium_article1/pages/Page1.dart';
import 'package:medium_article1/pages/Page2.dart';
import 'package:medium_article1/pages/Page3.dart';
import 'package:flutter/material.dart';


class PageViewScreen extends StatefulWidget {
@override
_PageViewScreenState createState() => _PageViewScreenState();
}

class _PageViewScreenState extends State<PageViewScreen> {

PageController pageController = PageController();
int currentIndex = 0;
var currentTabs = [
Page1(),
Page2(),
Page3()
];

@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
children: currentTabs,
controller: pageController,
onPageChanged: (int index) {
setState(() {
currentIndex = index;
});
},
),
);
}
}

3. Coding the SignIn screen

import 'package:flutter/material.dart';

class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.white,
),
body: Center(
child: Text(
'Sign In Screen',
style: TextStyle(
color: Colors.black,
fontSize: 25
),
),
),
);
}
}

Note- Add PageViewScreen() in the home property of MaterialApp() in main.dart file.

3. Adding Timer in PageViewScreen

Here we add a periodic timer to change the pages after every 5 screens. Additionally, you can also use NeverScrollablePhysics() in the physics property of PageView to stop users from scrolling between pages.

First, we need to import dart:async to use the Timer.

import 'dart:async';

The Timer is used to create a periodic timer which after every 3 seconds increases the currentIndex if it is less than 2 or makes it 2 if it is 2, additionally you can also make it 0 in the else statement once it becomes 2 to restart the whole carousel-like effect again. Then I use pageController to access animateToPage and pass in the current index, duration of animation, and an animation.

Further, I disposed of the pageController to prevent any memory leaks.

@override
void initState() {
super.initState();
Timer.periodic(Duration(seconds: 3), (Timer timer) {
if (currentIndex < 2) {
currentIndex++;
pageController.animateToPage(
currentIndex,
duration: Duration(milliseconds: 350),
curve: Curves.easeIn,
);
} else {
currentIndex = 2;
}
});
}
@override
void dispose() {
pageController.dispose();
super.dispose();
}

Now the whole PageViewScreen code looks like this -

import 'dart:async';
import 'package:medium_article1/pages/Page1.dart';
import 'package:medium_article1/pages/Page2.dart';
import 'package:medium_article1/pages/Page3.dart';
import 'package:flutter/material.dart';


class PageViewScreen extends StatefulWidget {
@override
_PageViewScreenState createState() => _PageViewScreenState();
}

class _PageViewScreenState extends State<PageViewScreen> {

PageController pageController = PageController();
int currentIndex = 0;
var currentTabs = [
Page1(),
Page2(),
Page3()
];

@override
void initState() {
super.initState();
Timer.periodic(Duration(seconds: 3), (Timer timer) {
if (currentIndex < 2) {
currentIndex++;
pageController.animateToPage(
currentIndex,
duration: Duration(milliseconds: 350),
curve: Curves.easeIn,
);
} else {
currentIndex = 2;
}
});
}

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

@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
children: currentTabs,
controller: pageController,
onPageChanged: (int index) {
setState(() {
currentIndex = index;
});
},
),
);
}
}

4. Adding redirecting button on Page3

Now we need a button on Page3 which the user clicks and he is then redirected to the SignIn screen. We can also do this automatically without any button as explained by me in my previous article. You can find the article here.

I use pushReplacement as we don’t want the user to come back to this carousel of screens. Now the code for Page3 looks like this.

import 'package:flutter/material.dart';
import 'package:medium_article1/screens/SignIn.dart';

class Page3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Center(
child: Text(
'Page 3',
style: TextStyle(
color: Colors.black,
fontSize: 20
),
),
),
MaterialButton(
onPressed: () {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (c) => SignIn()));
},
child: Text(
'SignIn Page'
),
)
],
),
);
}
}
Output on my physical device

Always learning