This package allows you to create a storyboard like Instagram For now it's just an early release with a lot of useful functionality missing but it's already usable with some minor tweaks
Features
Present:
- A list of story buttons that can be marked as "watched" automatically
- 3D page view list view in Instagram
- Custom navigation
- Default story scaffold Missing yet:
- Button preloaders that allow the stories to be requested from the backend before opening
- Lazy loaders that preload visible the stories from the backend in the background
Getting started
The easiest way to get started is to use a built-in StoryListView to create story buttons It accepts a list of StoryButtonData objects. These objects contain all the settings for each story including the list of pages, the timing for each page and many other settings. The pages can be completely custom, they're just widgets.
Usage
Here's the completely working example:
class _StoryExamplePageState extends State<StoryExamplePage> {
Widget _createDummyPage({
required String text,
required String imageName,
bool addBottomBar = true,
}) {
return StoryPageScaffold(
bottomNavigationBar: addBottomBar
? SizedBox(
width: double.infinity,
height: kBottomNavigationBarHeight,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 8.0,
horizontal: 20.0,
),
child: Row(
children: [
Expanded(
child: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 2.0,
),
borderRadius: BorderRadius.circular(
50.0,
),
),
),
),
const Padding(
padding: EdgeInsets.all(8.0),
child: Icon(
Icons.send,
color: Colors.white,
),
),
],
),
),
)
: const SizedBox.shrink(),
body: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
'assets/images/$imageName.png',
),
fit: BoxFit.cover,
),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
text,
style: const TextStyle(
color: Colors.white,
fontSize: 30.0,
fontWeight: FontWeight.bold,
),
)
],
),
),
),
);
}
Widget _buildButtonText(String text) {
return Padding(
padding: const EdgeInsets.all(5.0),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
text,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
],
),
);
}
BoxDecoration _buildButtonDecoration(
String imageName,
) {
return BoxDecoration(
image: DecorationImage(
image: AssetImage(
'assets/images/$imageName.png',
),
fit: BoxFit.cover,
),
);
}
BoxDecoration _buildBorderDecoration(Color color) {
return BoxDecoration(
borderRadius: const BorderRadius.all(
Radius.circular(15.0),
),
border: Border.fromBorderSide(
BorderSide(
color: color,
width: 1.5,
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.0,
title: const Text('Story Example'),
),
body: Column(
children: [
StoryListView(
pageTransform: const StoryPage3DTransform(),
buttonDatas: [
StoryButtonData(
timelineBackgroundColor: Colors.red,
buttonDecoration: _buildButtonDecoration('car'),
child: _buildButtonText('Want a new car?'),
borderDecoration: _buildBorderDecoration(Colors.red),
storyPages: [
_createDummyPage(
text:
'Want to buy a new car? Get our loan for the rest of your life!',
imageName: 'car',
),
_createDummyPage(
text:
'Can\'t return the loan? Don\'t worry, we\'ll take your soul as a collateral ;-)',
imageName: 'car',
),
],
segmentDuration: const Duration(seconds: 3),
),
StoryButtonData(
timelineBackgroundColor: Colors.blue,
buttonDecoration: _buildButtonDecoration('travel_1'),
borderDecoration:
_buildBorderDecoration(const Color.fromARGB(255, 134, 119, 95)),
child: _buildButtonText('Travel whereever'),
storyPages: [
_createDummyPage(
text: 'Get a loan',
imageName: 'travel_1',
addBottomBar: false,
),
_createDummyPage(
text: 'Select a place where you want to go',
imageName: 'travel_2',
addBottomBar: false,
),
_createDummyPage(
text: 'Dream about the place and pay our interest',
imageName: 'travel_3',
addBottomBar: false,
),
],
segmentDuration: const Duration(seconds: 3),
),
StoryButtonData(
timelineBackgroundColor: Colors.orange,
borderDecoration: _buildBorderDecoration(Colors.orange),
buttonDecoration: _buildButtonDecoration('house'),
child: _buildButtonText('Buy a house anywhere'),
storyPages: [
_createDummyPage(
text: 'You cannot buy a house. Live with it',
imageName: 'house',
),
],
segmentDuration: const Duration(seconds: 5),
),
StoryButtonData(
timelineBackgroundColor: Colors.red,
buttonDecoration: _buildButtonDecoration('car'),
child: _buildButtonText('Want a new car?'),
borderDecoration: _buildBorderDecoration(Colors.red),
storyPages: [
_createDummyPage(
text:
'Want to buy a new car? Get our loan for the rest of your life!',
imageName: 'car',
),
_createDummyPage(
text:
'Can\'t return the loan? Don\'t worry, we\'ll take your soul as a collateral ;-)',
imageName: 'car',
),
],
segmentDuration: const Duration(seconds: 3),
),
StoryButtonData(
buttonDecoration: _buildButtonDecoration('travel_1'),
borderDecoration:
_buildBorderDecoration(const Color.fromARGB(255, 134, 119, 95)),
child: _buildButtonText('Travel whereever'),
storyPages: [
_createDummyPage(
text: 'Get a loan',
imageName: 'travel_1',
addBottomBar: false,
),
_createDummyPage(
text: 'Select a place where you want to go',
imageName: 'travel_2',
addBottomBar: false,
),
_createDummyPage(
text: 'Dream about the place and pay our interest',
imageName: 'travel_3',
addBottomBar: false,
),
],
segmentDuration: const Duration(seconds: 3),
),
StoryButtonData(
timelineBackgroundColor: Colors.orange,
borderDecoration: _buildBorderDecoration(Colors.orange),
buttonDecoration: _buildButtonDecoration('house'),
child: _buildButtonText('Buy a house anywhere'),
storyPages: [
_createDummyPage(
text: 'You cannot buy a house. Live with it',
imageName: 'house',
),
],
segmentDuration: const Duration(seconds: 5),
),
],
),
],
),
);
}
}
Additional information
The package is under lazy construction. It is required in some projects I'm working on but not so much yet so I'm not implementing new features very quickly If you want to take part in the development, please feel free to make pull requests but make sure your code corresponds to major Dart language guidelines