ig_story
A player widget to implement Stories like Instagram.
Installation
To use this plugin, add ig_story
as a dependency in your pubspec.yaml file.
Usage
Import the package into your code
import "package:ig_story/ig_story.dart";
Basics
- Define
IgManager
to control the story's animation. - Create widgets which you want to display.
- Wrap each of them with
IgChild
. - Pass the IgChilds to
IgStory
. That's it.
Example
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
// Manager to control animation.
IgManager manager = IgManager();
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: IgStory(
manager: manager,
children: [
// Basic Widget
IgChild(
// Optional
duration: Duration(seconds: 2),
// Required: Any widget can be set.
child: Container(
color: Colors.red,
child: Center(
child: Text(
'first page',
style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold),
),
),
),
),
IgChild(
child: Container(
color: Colors.green,
child: Center(
child: Text(
'second page',
style: TextStyle(fontSize: 50, fontWeight: FontWeight.bold),
),
),
),
),
// Advanced usage
// After finished loading, trigger story animations.
IgChild(
child: Container(
width: double.infinity,
height: double.infinity,
child: MyImageLoader(
manager: manager,
),
),
),
],
),
);
}
}
// Example image loader widget.
// it's not this library's widget.
class MyImageLoader extends StatefulWidget {
final IgManager manager;
MyImageLoader({@required this.manager});
State createState() => new MyImageLoaderState();
}
class MyImageLoaderState extends State<MyImageLoader> {
Image _image = new Image.network(
'https://img.gifmagazine.net/gifmagazine/images/4407234/original.gif',
fit: BoxFit.cover,
);
bool _loading = true;
@override
void initState() {
super.initState();
_image.image
.resolve(ImageConfiguration())
.addListener(ImageStreamListener((ImageInfo info, bool syncCall) {
if (mounted) {
// Calls play() method after finished loading all image data.
widget.manager.play();
setState(() {
_loading = false;
});
}
}));
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
backgroundColor: Colors.black,
body: Container(
width: double.infinity,
height: double.infinity,
child: _loading ? new Text('Loading...') : _image,
),
),
);
}
}
Advanced
You can use IgStories
which is the wrapper to wrap up IgStory
widgets. The IgStory
widget wrapped IgStories
is animated to next IgStory
widget smoothly like Instagram's cube transition.
Example
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
IgManager manager = IgManager();
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: IgStories(
manager: manager,
children: [
// User A's Story
IgStory(
manager: manager,
children: [
IgChild(
child: Container(
color: Colors.red,
child: Center(
child: Text(
'first page',
style:
TextStyle(fontSize: 50, fontWeight: FontWeight.bold),
),
),
),
),
IgChild(
duration: Duration(seconds: 2),
child: Container(
color: Colors.green,
child: Center(
child: Text(
'second page',
style:
TextStyle(fontSize: 50, fontWeight: FontWeight.bold),
),
),
),
),
IgChild(
child: Container(
width: double.infinity,
height: double.infinity,
child: LoadedImage(
manager: manager,
url:
"https://img.gifmagazine.net/gifmagazine/images/4407234/medium_thumb.png",
),
),
),
],
),
// User B's Story
IgStory(
manager: manager,
children: [
IgChild(
child: Container(
color: Colors.blue,
child: Center(
child: Text(
'first page',
style:
TextStyle(fontSize: 50, fontWeight: FontWeight.bold),
),
),
),
),
IgChild(
child: Container(
width: double.infinity,
height: double.infinity,
child: LoadedImage(
manager: manager,
url:
"https://img.gifmagazine.net/gifmagazine/images/4381451/medium_thumb.png",
),
),
),
],
)
],
),
);
}
@override
void dispose() {
manager.controller.close();
super.dispose();
}
}
class LoadedImage extends StatefulWidget {
final String url;
final IgManager manager;
LoadedImage({@required this.manager, @required this.url});
State createState() => new LoadedImageState();
}
class LoadedImageState extends State<LoadedImage> {
Image _image;
bool _loading = true;
@override
void initState() {
super.initState();
_image = Image.network(
widget.url,
fit: BoxFit.cover,
);
_image.image
.resolve(ImageConfiguration())
.addListener(ImageStreamListener((ImageInfo info, bool syncCall) {
if (mounted) {
widget.manager.play();
setState(() {
_loading = false;
});
}
}));
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
backgroundColor: Colors.black,
body: Container(
width: double.infinity,
height: double.infinity,
child: _loading ? new Text('Loading...') : _image,
),
),
);
}
}