Logo

dev-resources.site

for different kinds of informations.

Understanding Flutter Pageview Widget(Making Instagram reels screen)

Published at
7/24/2022
Categories
flutter
android
develop
ios
Author
aakashp
Categories
4 categories in total
flutter
open
android
open
develop
open
ios
open
Author
7 person written this
aakashp
open
Understanding Flutter Pageview Widget(Making Instagram reels screen)

Hello readers, welcome back to another article. in the previous article we saw in detail about dismissible widget which we can use to implement slide to delete like the Gmail app.

Today in this article will see in detail the Pageview widget in flutter.
Thumbnail

What is Pageview Widget?

Pageview widget is similar to the list view. The only difference is the list view is used to show the list of items on a single screen whereas the page view shows a list of pages to scroll.

A pageview is useful when you want to show a list of full-screen images or videos or any other data. As you have seen in Instagram reels we see a video on a full page and when we scroll to another reel it's a different page.

Understanding Page View Constructor

PageView PageView({
  Key? key,
  Axis scrollDirection = Axis.horizontal,
  bool reverse = false,
  PageController? controller,
  ScrollPhysics? physics,
  bool pageSnapping = true,
  void Function(int)? onPageChanged,
  List<Widget> children = const <Widget>[],
  DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  bool allowImplicitScrolling = false,
  String? restorationId,
  Clip clipBehavior = Clip.hardEdge,
  ScrollBehavior? scrollBehavior,
  bool padEnds = true,
})
Enter fullscreen mode Exit fullscreen mode

As you can see in the constructor there are many different parameters we can tweak within the page view.

Let's see each of them one by one.

Scroll Direction
As the name suggests it is the direction in which we want our page view to scroll. Example Horizontal, Vertical.

ScrollDirection 1
ScrollDirection 2
Reverse

This is a Boolean value that reverses the scroll direction if set to true and default if false.

Reverse
Controller

The controller is a Page Controller which we can use to change the behavior of page view as per our requirements like in List view.

Physics

Physics defines the scroll behavior of the page view. There are multiple options like

  • NoScrollPhysics
  • BouncyScrollPhysics
  • and many other BouncyScrollPhysics

Page Snapping

This is also a boolean value which is when true the page will automatically drag to fit the screen while scrolling and if set false then the page will stop in between.

onPageChange

onPageChange is a function callback with one int parameter. This function is called whenever the page is changed in the page view. The int parameter represents the index of the page.

Here we will show a snack bar with the index of the page whenever the page changes in page view.

 onPageChanged: (int) {
        ScaffoldMessenger.of(context)
            .showSnackBar(SnackBar(content: Text("Page $int")));
      },
Enter fullscreen mode Exit fullscreen mode

onPageChange
Children

Children are the list of widgets that are to be shown in the page view.

 children: [
        Container(
          color: Colors.amberAccent,
        ),
        Container(
          color: Colors.red,
        ),
        Container(
          color: Colors.blue,
        ),
        Container(
          color: Colors.green,
        )
      ],
Enter fullscreen mode Exit fullscreen mode

drag start behavior (from flutter docs)

Determines the way that drag start behavior is handled.

If set to [DragStartBehavior.start], scrolling drag behavior will begin at the position where the drag gesture won the arena. If set to [DragStartBehavior.down] it will begin at the position where a down event is first detected.

In general, setting this to [DragStartBehavior.start] will make drag animation smoother, and setting it to [DragStartBehavior.down] will make drag behavior feel slightly more reactive.

By default, the drag start behavior is [DragStartBehavior.start].

allowImplicitScrolling

This is also a Boolean field that has no effect on normal users. It will be useful when the user is using the app via accessibility.

Controls whether the widget's pages will respond to [RenderObject.showOnScreen], allowing for implicit accessibility scrolling.

With this flag set to false, when accessibility focus reaches the end of the current page and the user attempts to move it to the next element, the focus will traverse to the next widget outside of the page view.

With this flag set to true, when accessibility focus reaches the end of the current page and the user attempts to move it to the next element, the focus will traverse to the next page in the page view.

restorationId

Restoration ID to save and restore the scroll offset of the scrollable.

If a restoration id is provided, the scrollable will persist its current scroll offset and restore it during state restoration.

The scroll offset is persisted in a [RestorationBucket] claimed from the surrounding [RestorationScope] using the provided restoration ID.

clipBehavior

clipBehavior is the parameter that defines what to do when the content of the page view goes outside of its boundary. There are multiple options available for clips like

1.Clip.antiAlias

2.Clip.antiAliasWithSaveLayer

3.Clip.hardEdge

ScrollBehavior

Scroll behavior is used to define the scroll behavior when the page view is at the start or bottom. As you can see in android we see a glowing light when we are at the end of the list.

padEnds

Whether to add padding to both ends of the list.

If this is set to true and [PageController.viewportFraction] < 1.0, padding will be added such that the first and last child slivers will be in the center of the viewport when scrolled all the way to the start or end, respectively.

If [PageController.viewportFraction] >= 1.0, this property has no effect.

This property defaults to true and must not be null.

Instagram Reels clone

we will make a reels screen clone only the UI part and instead of video, we will use here images to make it less complex.

First, we want to add the widget on top of the page so we need to use a stack.

First, let's create the bottom user name and description of the reels screen.
For this, we will use a Row to add a user image and name.

Row(
      children: const [
        CircleAvatar(
          backgroundColor: Colors.blue,
          radius: 20,
        ),
        SizedBox(
          width: 20,
        ),
        Text(
          "Name of user",
          style: TextStyle(color: Colors.white),
        ),
      ],
    );
Enter fullscreen mode Exit fullscreen mode

Image description
Then we will add this row into a column that contains the description of the video and also add some padding to it.

Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            mainAxisSize: MainAxisSize.min,
            children: const [
              CircleAvatar(
                backgroundColor: Colors.blue,
                radius: 20,
              ),
              SizedBox(
                width: 20,
              ),
              Text(
                "Name of user",
                style: TextStyle(color: Colors.white),
              ),
            ],
          ),
          const Text(
                "This is the very long description of the videos which has many lines This is the very long description of the videos which has many lines This is the very long description of the videos which has many lines This is the very long description of the videos which has many lines",
overflow: TextOverflow.ellipsis,
            softWrap: true,
            maxLines: 2,
            style: TextStyle(color: Colors.white),
          ),
        ],
      ),
    );
Enter fullscreen mode Exit fullscreen mode

Image description
Now you can see a render overflow error, this is because the text of the description does not have a horizontal bound.

Before solving this let's add the buttons of like and share on the right side. Just add the new button column and add the previous column in a row. Here I am not using the exact buttons icons that are used in reels.

class Buttons extends StatelessWidget {
  const Buttons({Key? key}) : super(key: key);
@override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        IconButton(
            onPressed: () {},
            icon: const Icon(
              Icons.heart_broken_outlined,
              color: Colors.white,
            )),
        IconButton(
            onPressed: () {},
            icon: const Icon(
              Icons.message_outlined,
              color: Colors.white,
            )),
        IconButton(
            onPressed: () {},
            icon: const Icon(
              Icons.share,
              color: Colors.white,
            )),
      ],
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Add this to the previous row. Now if we remove the description text for some time our UI will look like this.
Image description
Now bring back the description and wrap both the child of row into flex and give it the ratio of 8 and 1.

Now the overall code looks like this.

class SinglePage extends StatelessWidget {
  const SinglePage({Key? key}) : super(key: key);
@override
  Widget build(BuildContext context) {
    return Stack(children: [
      Container(color: Colors.red),
      Align(
        alignment: Alignment.bottomLeft,
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Flexible(
                flex: 8,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      mainAxisSize: MainAxisSize.min,
                      children: const [
                        CircleAvatar(
                          backgroundColor: Colors.blue,
                          radius: 20,
                        ),
                        SizedBox(
                          width: 20,
                        ),
                        Text(
                          "Name of user",
                          style: TextStyle(color: Colors.white),
                        ),
                      ],
                    ),
                    const Text(
                      "This is the very long description of the videos which has many lines This is the very long description of the videos which has many lines This is the very long description of the videos which has many lines This is the very long description of the videos which has many lines",
                      overflow: TextOverflow.ellipsis,
                      softWrap: true,
                      maxLines: 2,
                      style: TextStyle(color: Colors.white),
                    ),
                  ],
                ),
              ),
              const Flexible(flex: 1, child: Buttons())
            ],
          ),
        ),
      )
    ]);
  }
}
class Buttons extends StatelessWidget {
  const Buttons({Key? key}) : super(key: key);
@override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        IconButton(
            onPressed: () {},
            icon: const Icon(
              Icons.heart_broken_outlined,
              color: Colors.white,
            )),
        IconButton(
            onPressed: () {},
            icon: const Icon(
              Icons.message_outlined,
              color: Colors.white,
            )),
        IconButton(
            onPressed: () {},
            icon: const Icon(
              Icons.share,
              color: Colors.white,
            )),
      ],
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

And the UI looks like this.

Image description

Now just we have to add this single page into page view and give random colors to the background.

Final code

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
  HomeScreen({Key? key}) : super(key: key);
  final controller = PageController();
  @override
  Widget build(BuildContext context) {
    return PageView(
      controller: controller,
      scrollDirection: Axis.vertical,
      padEnds: false,
      children: const [
        SinglePage(
          color: Colors.red,
        ),
        SinglePage(
          color: Colors.green,
        ),
        SinglePage(
          color: Colors.yellow,
        ),
        SinglePage(color: Colors.amber),
        SinglePage(
          color: Colors.purple,
        ),
      ],
    );
  }
}
class SinglePage extends StatelessWidget {
  const SinglePage({
    Key? key,
    required this.color,
  }) : super(key: key);
  final Color color;
  @override
  Widget build(BuildContext context) {
    return Stack(children: [
      Container(color: color),
      Align(
        alignment: Alignment.bottomLeft,
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Flexible(
                flex: 8,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      mainAxisSize: MainAxisSize.min,
                      children: const [
                        CircleAvatar(
                          backgroundColor: Colors.blue,
                          radius: 20,
                        ),
                        SizedBox(
                          width: 20,
                        ),
                        Text(
                          "Name of user",
                          style: TextStyle(color: Colors.white),
                        ),
                      ],
                    ),
                    const Text(
                      "This is the very long description of the videos which has many lines This is the very long description of the videos which has many lines This is the very long description of the videos which has many lines This is the very long description of the videos which has many lines",
                      overflow: TextOverflow.ellipsis,
                      softWrap: true,
                      maxLines: 2,
                      style: TextStyle(color: Colors.white),
                    ),
                  ],
                ),
              ),
              const Flexible(flex: 1, child: Buttons())
            ],
          ),
        ),
      )
    ]);
  }
}
class Buttons extends StatelessWidget {
  const Buttons({Key? key}) : super(key: key);
@override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        IconButton(
            onPressed: () {},
            icon: const Icon(
              Icons.heart_broken_outlined,
              color: Colors.white,
            )),
        IconButton(
            onPressed: () {},
            icon: const Icon(
              Icons.message_outlined,
              color: Colors.white,
            )),
        IconButton(
            onPressed: () {},
            icon: const Icon(
              Icons.share,
              color: Colors.white,
            )),
      ],
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Final UI
Image description

develop Article's
30 articles in total
Favicon
AWS CLI: Instalación en Windows y Linux, y Uso Básico
Favicon
C Development with GNU Emacs
Favicon
Creating a Stunning WordPress Site from Scratch
Favicon
How to Develop a Game Like Garena Free Fire in Scratch?
Favicon
The 4 Essential Skills of the Software Developers
Favicon
Cracking Your Technical Interview with LeetCode: A Step-by-Step Guide
Favicon
Salesforce Developer : Learning the course
Favicon
Most useful chrome extensions for DEVELOPERS
Favicon
🐳 Announcing the Docker x Hacktoberfest 2022 Winners
Favicon
Business Needs Custom Software For
Favicon
How to get Paid as Web3.0 Developer
Favicon
CARREIRA DEV: por onde começar?
Favicon
How Chatbots Are Revolutionizing The Way Businesses Interact With Customers
Favicon
Understanding Flutter Pageview Widget(Making Instagram reels screen)
Favicon
Programmer's life
Favicon
🙊 What do the Developer Advocates do? - Dev Advocate Journal (#DAJ) Day 1
Favicon
Resizing of Roles in IT
Favicon
Creating charts with the Aha! Develop API and extensions
Favicon
Why do I like to learn?
Favicon
10 Trending & Different Types of Software Development
Favicon
Common Ninja Platform News: Payments | New E-Commerce APIs
Favicon
14 Exemplos de código limpo e encurtamento de código Javascript
Favicon
50 Integrações de API mais populares
Favicon
Creating a java library, a place where any problem can be resolved.
Favicon
Why Do Businesses Need To Hire Application Maintenance & Support Services?
Favicon
SoC - Separation of Concerns
Favicon
The top advantages of software developer jobs.
Favicon
Goodbye Adobe! Or: why we are leaving the Adobe product family!
Favicon
5 Online Websites To Help You Learn Web Development
Favicon
Developed an app to transcribe and translate from images

Featured ones: