A highly customizable flutter implementation of instagram-style story page view, which renders a page view that turns to next after after a given period of time. An page indicator with animated timer can be included too.
Add story_page_view
to pubspec.yaml
:
flutter pub add story_page_view
The widget is super easy to use:
StoryPageView(
children: [
Container(color: Colors.red),
Container(color: Colors.orange),
Container(color: Colors.yellow),
Container(color: Colors.green),
Container(color: Colors.blue),
Container(color: Colors.indigo),
Container(color: Colors.purple),
],
);
Changing the timer for each page is easy:
StoryPageView(
storyDuration: const Duration(seconds: 5),
)
Similar to PageView
, StoryPageView
uses StoryPageController
to control its behaviour. StoryPageController
is a special type of PageController
that used by PageView
, which supports all features from PageController
.
Beyond PageController
, StoryPageController
also controls the paging animation. The paging animation can be customised by StoryPageController
.
StoryPageView(
controller: StoryPageController(
pagingCurve: Curves.elasticOut,
pagingDuration: const Duration(milliseconds: 2000),
),
)
StoryPageView(
indicatorStyle: StoryPageIndicatorStyle(
height: 6,
gap: 12,
unvisitedColor: Colors.blue.shade200,
visitedColor: Colors.blue.shade900,
timerBarBackgroundColor: Colors.blue.shade300, // default to unvisitedColor if not given or is null
timerBarColor: Colors.blue.shade700, // default to visitedColor if not given or is null
shape: RoundedRectangleBorder( // Change Shape
borderRadius: BorderRadius.circular(12),
),
),
)
When StoryPageIndicatorPosition.overlay
is used for indicatorPosition
, the page indicator will be rendered as an overlay that floating on top of the content. And page indicator can be positioned with absolute coordinates.
e.g:
StoryPageView(
// Align to the top middle
indicatorPosition: StoryPageIndicatorPosition.overlay(
top: 32,
left: 12,
right: 12,
),
)
or
StoryPageView(
// Align to the bottom middle
indicatorPosition: StoryPageIndicatorPosition.overlay(
bottom: 32,
left: 12,
right: 12,
),
)
In fact the widget allow developer to fully control the layout by using StoryPageIndicatorPosition.custom
.
A special builder function is needed to declare the expected layout, the PageView
widget and StorypageIndicator
widget instance will be passed as parameter to the builder function.
For example, the following code put the page indicator and page view in a column:
StoryPageView(
indicatorPosition: StoryPageIndicatorPosition.custom(
layoutBuilder: (c, pageView, indicator) => SafeArea(
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
child: indicator, // Page Indicator
),
Expanded(
child: pageView, // PageView
),
],
),
),
),
)
StoryPageView(
// Customize indicator looking
indicatorStyle: StoryPageIndicatorStyle(
height: 6,
gap: 12,
unvisitedColor: Colors.blue.shade200,
visitedColor: Colors.blue.shade900,
timerBarBackgroundColor:
Colors.blue.shade300, // default to unvisitedColor
timerBarColor: Colors.blue.shade700, // default to vistedColor
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
controller: StoryPageController(
// Customize paging animation style
pagingCurve: Curves.elasticOut,
pagingDuration: const Duration(milliseconds: 2000),
),
storyDuration: const Duration(seconds: 5),
// Customize whole layout
indicatorPosition: StoryPageIndicatorPosition.custom(
layoutBuilder: (c, pageView, indicator) => SafeArea(
child: Column(
children: [
// Put page indicator on top of the pager
Padding(
padding: const EdgeInsets.symmetric(
vertical: 8,
horizontal: 12,
),
child: indicator,
),
Expanded(
child: pageView,
),
],
),
),
),
children: [
Container(color: Colors.red),
Container(color: Colors.orange),
Container(color: Colors.yellow),
Container(color: Colors.green),
Container(color: Colors.blue),
Container(color: Colors.indigo),
Container(color: Colors.purple),
],
)
Sometimes developer might want to hide the page indicator, it can be done by using StoryPageIndicatorPosition.none
.
StoryPageView(
storyDuration: const Duration(seconds: 1),
// No page indicator, timer only
indicatorPosition: const StoryPageIndicatorPosition.none(),
// Make the view port only 95% of the screen width
controller: StoryPageController(
viewportFraction: 0.95,
),
children: [
Container(color: Colors.red),
Container(color: Colors.orange),
Container(color: Colors.yellow),
Container(color: Colors.green),
Container(color: Colors.blue),
Container(color: Colors.indigo),
Container(color: Colors.purple),
],
),