Skip to content

Instantly share code, notes, and snippets.

@diegoveloper
Created January 13, 2020 23:36
Show Gist options
  • Select an option

  • Save diegoveloper/5536c9d19d9ea15874416dc4835ba06d to your computer and use it in GitHub Desktop.

Select an option

Save diegoveloper/5536c9d19d9ea15874416dc4835ba06d to your computer and use it in GitHub Desktop.
header_navigation
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