Prerequisites
Tools required to follow the article.
- Flutter SDK.
- Android Studio or VS code.
- Emulator or an Android device
- Background knowledge of Flutter and Dart
Although there is a packaged already built to do this, there is an advantage getting thing done yourself, one of which customizing the design pattern to suit you. I will take you through achieving this without an external help of a provider.
Setup
Create a new project with the command below
flutter create your_app_name
Open the folder on your preferred text editor and open the main.dart
which is in lib
folder and replace the the code with:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(),
);
}
}
To achieve the goal at hand flutter already have a widget called PageView
Widget, so my job is to show you how this can be used.
PageView
A PageView
allows the user to swipe between different screens in your app. All you need to set it up are a PageViewController
which is a required property of the PageView. Each or widget to be swiped is wrapped inside a list of Widget as children.
Time to See how the magic works
Initializing PageController
Inside the stateful widget create controller
variable whose type is of PageViewController
and another int
variable to hold the current index of the page
PageController _pageController;
int currentIndex = 0;
Initialize the state, add the following code after declaring of the page controller’s variable
@override
void initState() {
super.initState();
_pageController = PageController();
}
Also the controller needs to be disposed, to do this add the following code after the last previous one
@override
void dispose() {
_pageController.dispose();
super.dispose();
}
Building Screens
Update the body of your scaffold with the following code
PageView(
controller: _pageController,
children: <Widget>[
Container(
child: Text("First Screen")
),
Container(
child: Text("Second Screen")
),
Container(
child: Text("Third Screen")
)
],
),
Adding Indicators
It is common in different application with onboarding screens to see indicators to which screen is currently viewed. The PageView
has provision for function which listen to the change in screen and return the index of the current screen. You will create a custom stateless widget for the indicator, and place it in the view. Create the Indicator widget with the code below outside the MyHomePage
class Indicator extends StatelessWidget {
final int positionIndex, currentIndex;
const Indicator({this.currentIndex, this.positionIndex});
@override
Widget build(BuildContext context) {
return Container(
height: 12,
width: 12,
decoration: BoxDecoration(
border: Border.all(color: Colors.blue),
color: positionIndex == currentIndex
? Colors.blue
: Colors.transparent,
borderRadius: BorderRadius.circular(100)),
);
}
}
Now you have wrap the PageView
widget in Stack
widgets so you can position another thing on the screen and where ever you wish to place it.
body: Stack(
children: <Widget>[
PageView(
controller: _pageController,
children: <Widget>[
Container(child: Text("First Screen")),
Container(child: Text("Second Screen")),
Container(child: Text("Third Screen"))
],
),
],
),
For the Indicator, it is going to be placed at the bottom of the screen in a row. add the following code as the second widget in the stack
Positioned(
bottom: 60,
left: 150,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Indicator(
positionIndex: 0,
currentIndex: currentIndex,
),
SizedBox(
width: 10,
),
Indicator(
positionIndex: 1,
currentIndex: currentIndex,
),
SizedBox(
width: 10,
),
Indicator(
positionIndex: 2,
currentIndex: currentIndex,
),
],
),
),
Now you will create a method to update the index of the page once it is changed
onChangedFunction(int index) {
setState(() {
currentIndex = index;
});
}
As earlier mentioned the PageView
has a property called onPageChanged
which takes a method and return the index of the current page. go ahead and add the method above to the PageView
widget
onPageChanged: onChangedFunction,
Next and Previous Button
Lastly, you can also add a next or previous button to your page. You can do this by acessing the nextPage
and previousPage
which are both methods built into the PageController
and takes two parameter duration
which takes the duration for the page to switch, and curve
type of transition animation you want to apply while changing. create two static for duration
and the curve
after _pageController
static const _kDuration = const Duration(milliseconds: 300);
static const _kCurve = Curves.ease;
Also Create two methods to handle both functions respectively
nextFunction() {
_pageController.nextPage(duration: _kDuration, curve: _kCurve);
}
previousFunction() {
_pageController.previousPage(duration: _kDuration, curve: _kCurve);
}
Update your view by adding this as the last widget in the stack
Positioned(
bottom: 30,
left: 130,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Container(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
InkWell(
onTap: () => previousFunction(),
child: Text("Previous")),
SizedBox(
width: 50,
),
InkWell(onTap: () => nextFunction(), child: Text("Next"))
],
),
),
),
)
Top comments (2)
Great post, thanks for sharing
You are welcome