Skip to content

Instantly share code, notes, and snippets.

@benpye
Last active April 19, 2018 17:08
Show Gist options
  • Save benpye/975b92964c9fc576bfe9f1db23c4da91 to your computer and use it in GitHub Desktop.
Save benpye/975b92964c9fc576bfe9f1db23c4da91 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
void main() {
MaterialPageRoute.debugEnableFadingRoutes = true; // ignore: deprecated_member_use
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Reader',
theme: new ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or press Run > Flutter Hot Reload in IntelliJ). Notice that the
// counter didn't reset back to zero; the application is not restarted.
primarySwatch: Colors.blue,
),
home: new BottomNavigationDemo(),
);
}
}
class NavigationIconView {
NavigationIconView({
Widget icon,
String title,
Color color,
TickerProvider vsync,
}) : _icon = icon,
_color = color,
_title = title,
item = new BottomNavigationBarItem(
icon: icon,
title: new Text(title),
backgroundColor: color,
),
controller = new AnimationController(
duration: kThemeAnimationDuration,
vsync: vsync,
) {
_animation = new CurvedAnimation(
parent: controller,
curve: const Interval(0.5, 1.0, curve: Curves.fastOutSlowIn),
);
}
final Widget _icon;
final Color _color;
final String _title;
final BottomNavigationBarItem item;
final AnimationController controller;
CurvedAnimation _animation;
FadeTransition transition(BottomNavigationBarType type, BuildContext context) {
return new FadeTransition(
opacity: _animation,
child: new SlideTransition(
position: new Tween<Offset>(
begin: const Offset(0.0, 0.02), // Slightly down.
end: Offset.zero,
).animate(_animation),
child: new IconTheme(
data: new IconThemeData(
color: _color,
size: 120.0,
),
child: new Semantics(
label: 'Placeholder for $_title tab',
child: _icon,
),
),
),
);
}
}
class CustomIcon extends StatelessWidget {
@override
Widget build(BuildContext context) {
final IconThemeData iconTheme = IconTheme.of(context);
return new Container(
margin: const EdgeInsets.all(4.0),
width: iconTheme.size - 8.0,
height: iconTheme.size - 8.0,
color: iconTheme.color,
);
}
}
class BottomNavigationDemo extends StatefulWidget {
static const String routeName = '/material/bottom_navigation';
@override
_BottomNavigationDemoState createState() => new _BottomNavigationDemoState();
}
class _BottomNavigationDemoState extends State<BottomNavigationDemo>
with TickerProviderStateMixin {
int _currentIndex = 0;
BottomNavigationBarType _type = BottomNavigationBarType.shifting;
List<NavigationIconView> _navigationViews;
@override
void initState() {
super.initState();
_navigationViews = <NavigationIconView>[
new NavigationIconView(
icon: const Icon(Icons.rss_feed),
title: 'Unread',
color: Colors.deepPurple,
vsync: this,
),
new NavigationIconView(
icon: new Icon(Icons.favorite),
title: 'Favorites',
color: Colors.deepOrange,
vsync: this,
),
new NavigationIconView(
icon: const Icon(Icons.history),
title: 'History',
color: Colors.teal,
vsync: this,
),
new NavigationIconView(
icon: const Icon(Icons.category),
title: 'Categories',
color: Colors.indigo,
vsync: this,
),
];
for (NavigationIconView view in _navigationViews)
view.controller.addListener(_rebuild);
_navigationViews[_currentIndex].controller.value = 1.0;
}
@override
void dispose() {
for (NavigationIconView view in _navigationViews)
view.controller.dispose();
super.dispose();
}
void _rebuild() {
setState(() {
// Rebuild in order to animate views.
});
}
Widget _buildTransitionsStack() {
final List<FadeTransition> transitions = <FadeTransition>[];
for (NavigationIconView view in _navigationViews)
transitions.add(view.transition(_type, context));
// We want to have the newly animating (fading in) views on top.
transitions.sort((FadeTransition a, FadeTransition b) {
final Animation<double> aAnimation = a.opacity;
final Animation<double> bAnimation = b.opacity;
final double aValue = aAnimation.value;
final double bValue = bAnimation.value;
return aValue.compareTo(bValue);
});
return new Stack(children: transitions);
}
@override
Widget build(BuildContext context) {
final BottomNavigationBar botNavBar = new BottomNavigationBar(
items: _navigationViews
.map((NavigationIconView navigationView) => navigationView.item)
.toList(),
currentIndex: _currentIndex,
type: _type,
onTap: (int index) {
setState(() {
_navigationViews[_currentIndex].controller.reverse();
_currentIndex = index;
_navigationViews[_currentIndex].controller.forward();
});
},
);
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
return new Scaffold(
appBar: new AppBar(
title: const Text('Reader'),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.settings),
tooltip: 'Settings',
onPressed: () {
_scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text('Open Settings!'),
));
},
)
]
),
body: new Center(
child: _buildTransitionsStack()
),
bottomNavigationBar: botNavBar,
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment