Flutter - Creating PageView with PageController Examples

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:

Flutter - PageView

 

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:

Flutter - PageView - scrollDirection vertical

 

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:

Flutter - PageView - physics BouncingScrollPhysics

 

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:

Flutter - PageView - pageSnapping false

 

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 to Axis.horizontal.
  • reverse: Whether the page view scrolls in the reading direction. Defaults to false.
  • PageController controller: Controller for the PageView.
  • ScrollPhysics physics: How the page view should respond to user input.
  • bool pageSnapping: Whether to use page snapping. Defaults to true.
  • 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 to DragStartBehavior.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 the PageView.

*: Required.