Instantly share code, notes, and snippets.
Created
January 13, 2020 23:36
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
-
Save diegoveloper/5536c9d19d9ea15874416dc4835ba06d to your computer and use it in GitHub Desktop.
header_navigation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'package:flutter/material.dart'; | |
| final Color darkBlue = Color.fromARGB(255, 18, 32, 47); | |
| void main() { | |
| runApp(MyApp()); | |
| } | |
| class MyApp extends StatelessWidget { | |
| @override | |
| Widget build(BuildContext context) { | |
| return MaterialApp( | |
| theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue), | |
| debugShowCheckedModeBanner: false, | |
| home: Scaffold( | |
| body: Center( | |
| child: MainHeaderNavigation(), | |
| ), | |
| ), | |
| ); | |
| } | |
| } | |
| class MainHeaderNavigation extends StatelessWidget { | |
| @override | |
| Widget build(BuildContext context) { | |
| return SafeArea( | |
| child: Scaffold( | |
| body: HeaderNavigation( | |
| items: [ | |
| HeaderNavigationItem( | |
| colorBackground: Colors.purple, | |
| title: "SERVICES", | |
| colorForeground: Colors.white, | |
| icon: Icon( | |
| Icons.room_service, | |
| size: 45, | |
| ), | |
| child: ContentNavigation( | |
| color: Colors.purple, | |
| ), | |
| ), | |
| HeaderNavigationItem( | |
| colorBackground: Colors.red, | |
| title: "AUTO", | |
| colorForeground: Colors.white, | |
| icon: Icon( | |
| Icons.directions_car, | |
| size: 45, | |
| ), | |
| child: ContentNavigation( | |
| color: Colors.red, | |
| ), | |
| ), | |
| HeaderNavigationItem( | |
| colorBackground: Colors.green, | |
| title: "JOB", | |
| colorForeground: Colors.white, | |
| icon: Icon( | |
| Icons.person, | |
| size: 45, | |
| ), | |
| child: ContentNavigation( | |
| color: Colors.green, | |
| ), | |
| ), | |
| HeaderNavigationItem( | |
| colorBackground: Colors.blue, | |
| title: "REALTY", | |
| colorForeground: Colors.white, | |
| icon: Icon( | |
| Icons.home, | |
| size: 45, | |
| ), | |
| child: ContentNavigation( | |
| color: Colors.blue, | |
| ), | |
| ), | |
| ], | |
| ), | |
| ), | |
| ); | |
| } | |
| } | |
| class ContentNavigation extends StatelessWidget { | |
| final Color color; | |
| const ContentNavigation({Key key, this.color}) : super(key: key); | |
| @override | |
| Widget build(BuildContext context) { | |
| return GridView.count( | |
| crossAxisCount: 2, | |
| childAspectRatio: 1 / 1.5, | |
| mainAxisSpacing: 10, | |
| crossAxisSpacing: 15, | |
| padding: const EdgeInsets.all(15), | |
| children: [ | |
| ContentItem( | |
| color: color, | |
| ), | |
| ContentItem( | |
| color: color, | |
| ), | |
| ContentItem( | |
| color: color, | |
| ), | |
| ContentItem( | |
| color: color, | |
| ), | |
| ], | |
| ); | |
| } | |
| } | |
| class ContentItem extends StatelessWidget { | |
| final Color color; | |
| const ContentItem({Key key, this.color}) : super(key: key); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Container( | |
| color: color.withOpacity(0.5), | |
| alignment: Alignment.bottomCenter, | |
| child: Padding( | |
| padding: const EdgeInsets.all(8.0), | |
| child: Column( | |
| mainAxisSize: MainAxisSize.min, | |
| crossAxisAlignment: CrossAxisAlignment.stretch, | |
| children: [ | |
| Container( | |
| height: 7, | |
| color: color.withOpacity(0.6), | |
| ), | |
| const SizedBox( | |
| height: 5, | |
| ), | |
| Container( | |
| height: 7, | |
| margin: const EdgeInsets.only(right: 10), | |
| color: color.withOpacity(0.6), | |
| ), | |
| const SizedBox( | |
| height: 15, | |
| ), | |
| ], | |
| ), | |
| ), | |
| ); | |
| } | |
| } | |
| class HeaderNavigationItem { | |
| final Color colorBackground; | |
| final Color colorForeground; | |
| final Widget icon; | |
| final String title; | |
| final Widget child; | |
| HeaderNavigationItem( | |
| {this.colorBackground = Colors.blue, | |
| this.colorForeground = Colors.white, | |
| this.icon, | |
| this.child, | |
| @required this.title}); | |
| } | |
| class HeaderNavigation extends StatefulWidget { | |
| final List<HeaderNavigationItem> items; | |
| final Duration duration; | |
| const HeaderNavigation({ | |
| Key key, | |
| @required this.items, | |
| this.duration = const Duration( | |
| milliseconds: 400, | |
| ), | |
| }) : super(key: key); | |
| @override | |
| _HeaderNavigationState createState() => _HeaderNavigationState(); | |
| } | |
| class _HeaderNavigationState extends State<HeaderNavigation> { | |
| int _currentIndex = 0; | |
| final _keyLayout = GlobalKey(); | |
| double _heightLayout = 0; | |
| bool _open = true; | |
| void _onItemTapped(int index) { | |
| if (!_open) { | |
| setState(() { | |
| _currentIndex = index; | |
| _open = true; | |
| }); | |
| return; | |
| } | |
| setState(() { | |
| _currentIndex = index; | |
| _open = false; | |
| }); | |
| } | |
| @override | |
| void initState() { | |
| WidgetsBinding.instance.addPostFrameCallback((_) { | |
| setState(() { | |
| _heightLayout = | |
| (_keyLayout.currentContext.findRenderObject() as RenderBox) | |
| .size | |
| .height; | |
| }); | |
| }); | |
| super.initState(); | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| final count = widget.items.length; | |
| final verticalItems = List<Widget>(); | |
| if (_heightLayout > 0) { | |
| final heightPerItem = _heightLayout / count; | |
| for (int i = count - 1; i >= 0; i--) { | |
| final item = widget.items[i]; | |
| double itemSize = heightPerItem; | |
| if (!_open) { | |
| if (_currentIndex == i) { | |
| itemSize = kToolbarHeight; | |
| } else { | |
| itemSize = 0; | |
| } | |
| } | |
| final text = Text( | |
| item.title, | |
| style: TextStyle( | |
| fontSize: 16, | |
| color: item.colorForeground, | |
| ), | |
| ); | |
| verticalItems.add(AnimatedPositioned( | |
| duration: widget.duration, | |
| top: !_open ? 0 : i * heightPerItem, | |
| height: itemSize, | |
| left: 0, | |
| right: 0, | |
| child: InkWell( | |
| onTap: () { | |
| _onItemTapped(i); | |
| }, | |
| child: Container( | |
| alignment: Alignment.center, | |
| child: Stack( | |
| children: [ | |
| Column( | |
| mainAxisSize: MainAxisSize.min, | |
| mainAxisAlignment: MainAxisAlignment.center, | |
| children: [ | |
| if (_open) | |
| Expanded( | |
| flex: 2, | |
| child: ClipRect( | |
| //remove shadermask and it will work. | |
| child: true ? ShaderMask( | |
| shaderCallback: (bounds) => LinearGradient( | |
| colors: [ | |
| item.colorForeground, | |
| item.colorForeground | |
| ], | |
| tileMode: TileMode.mirror, | |
| ).createShader(bounds), | |
| blendMode: BlendMode.srcIn, | |
| child: item.icon, | |
| ): const SizedBox.shrink(), | |
| ), | |
| ), | |
| Expanded( | |
| child: _open | |
| ? text | |
| : Center( | |
| child: text, | |
| ), | |
| ), | |
| ], | |
| ), | |
| if (!_open) | |
| Positioned( | |
| left: 0, | |
| right: 0, | |
| bottom: 5, | |
| child: ClipRect( | |
| child: Icon( | |
| Icons.keyboard_arrow_down, | |
| color: item.colorForeground, | |
| size: 10, | |
| ), | |
| ), | |
| ), | |
| ], | |
| ), | |
| decoration: BoxDecoration( | |
| color: item.colorBackground, | |
| boxShadow: [ | |
| BoxShadow( | |
| offset: Offset(2, 1), | |
| spreadRadius: 2, | |
| blurRadius: 10, | |
| ) | |
| ], | |
| ), | |
| ), | |
| ), | |
| )); | |
| } | |
| } | |
| return Scaffold( | |
| body: Stack( | |
| key: _keyLayout, | |
| children: [ | |
| Positioned( | |
| top: kToolbarHeight, | |
| bottom: 0, | |
| left: 0, | |
| right: 0, | |
| child: IndexedStack( | |
| index: _currentIndex, | |
| children: widget.items.map((item) => item.child).toList(), | |
| ), | |
| ), | |
| Stack( | |
| children: verticalItems, | |
| ), | |
| ], | |
| ), | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment