This tutorial shows you how to use Flutter's PageView
along with its PageController
.
In Flutter, PageView
is a scrollable list that works page by page. It contains multiple children (List<Widget>
), with each child is forced to be the same size as the viewport. To navigate between children (pages), the user needs to scroll the list. A PageView
can have a PageController
, one of its responsibilities is to set which page should be visible.
In this tutorial I'm going to show you how to use Flutter's PageView
, which includes the basic usage, setting PageController
, orientation, physics, snaping behavior, as well as handling page changed.
Creating PageView
To create a PageView
, you can use the constructor. Though there is no required parameter, you should pass children
(List<Widget>
). Otherwise it will show nothing.
For this tutorial, we are going to use the following list of widgets as the children
.
List<Widget> pages = [
Container(
color: Colors.red,
),
Container(
color: Colors.blue,
),
Container(
color: Colors.green,
),
];
Below is a basic example of how to use PageView
. You only need to pass the widgets as children
and Flutter will create a scrollable list.
PageView(
children: pages,
)
Output:
Another way to create a PageView
is by using .builder
named constructor. The page widgets will be created on-demand. You need to pass itemBuilder
(IndexedWidgetBuilder
) which is responsible to create the page widgets. To limit the number of pages, set the itemCount
property.
PageView(
itemBuilder: (BuilderContext context, int index) {
Color color;
if (index % 3 == 0) {
color = Colors.red;
} else if (index % 3 == 1) {
color = Colors.blue;
} else {
color = Colors.green;
}
return Container(color: color);
},
itemCount: 3,
)
You can also use .custom
named constructor that creates a scrollable list using custom page model.
PageView.custom( childrenDelegate: SliverChildBuilderDelegate( (BuildContext context, int index) { Color color; if (index % 3 == 0) { color = Colors.red; } else if (index % 3 == 1) { color = Colors.blue; } else { color = Colors.green; } return Container(color: color); }, childCount: 3, ), )
You can read the list of properties at the bottom of this tutorial.
Setting PageController
PageController
is used to control the PageView
. That's include which page should be shown first, how each page should occupy the viewport, as well as whether to keep the page number when the scrollable is recreated.
There are three properties you can pass to customize the controller
int initialPage
: Index of the first page to show.bool keepPage
: Whether to save the current page number and restrore it when the scrollable is recreated.double viewportFraction
: The fraction of the viewport that each page should occupy.
Below is a simple PageController
that sets the second page as the initial page (the index starts from 0).
static final controller = PageController(
initialPage: 1,
);
Pass the controller to the PageView
to use it.
PageView(
children: pages,
controller: controller,
)
Setting Scroll Direction
The default scroll direction is horizontal To change it to vertical, set scrollDirection
property to Axis.vertical
.
PageView(
children: pages,
scrollDirection: Axis.vertical,
)
Output:
Setting Physics
Flutter also lets you to define the used physics (ScrollPhysics
), which affects how the page response to user input. For example, by setting physics
to BouncingScrollPhysics()
, the user will get bouncing effect when reaching the top or bottom of the scrollable. Other compatibles physics such as NeverScrollableScrollPhysics
, AlwaysScrollableScrollPhysics
, PageScrollPhysics
, and ClampingScrollPhysics
,
PageView(
children: children,
physics: BouncingScrollPhysics(),
)
Output:
Setting PageSnapping
By default, snipping is enabled, which means each scroll can only stop at certain position where the current page is right in the center. You can disable it by setting pageSnapping
property to false
.
PageView(
children: children,
pageSnapping: false,
)
Output:
Handle Page Changed
You can provide a callback function that will be called whenever the user scrolls to another page. What you need to do is passing a ValueChanged<int>
function, which accepts one parameter of type integer representing the page index, as onPageChanged
parameter.
PageView(
children: children,
onPageChanged: (index) => {
print(index)
},
)
PageView
Properties
Below is the list of available properties you can pass as the constructor parameters.
Key key
: The widget key, used to control if it's should be replaced.scrollDirection
: The axis along which the page view scrolls. Defaults toAxis.horizontal
.reverse
: Whether the page view scrolls in the reading direction. Defaults tofalse
.PageController controller
: Controller for thePageView
.ScrollPhysics physics
: How the page view should respond to user input.bool pageSnapping
: Whether to use page snapping. Defaults totrue
.ValueChanged<int> onPageChanged
: Callback that will be called whenever a different page becomes the center.DragStartBehavior dragStartBehavior
: How the drag start behavior is handled. Defaults toDragStartBehavior.start
.List <Widget> children
(only for default constructor): Collection of widgets, each represeting a page.IndexedWidgetBuilder itemBuilder
(only for.builder()
)*: Function that creates a widget for the given index number.int itemCount
(only for.builder()
): Used to set the maximum page.SliverChildDelegate childrenDelegate
(only for.custom()
)*: A delegate that provides the children for thePageView
.
*: Required.