Skip to content

Instantly share code, notes, and snippets.

@Fiyiin
Last active December 9, 2020 15:45
Show Gist options
  • Save Fiyiin/d76156b76df8a1a7b3e38b065df249ea to your computer and use it in GitHub Desktop.
Save Fiyiin/d76156b76df8a1a7b3e38b065df249ea to your computer and use it in GitHub Desktop.
Tabbed Profile Layout
import 'package:flutter/material.dart';
import 'dart:math' as math;
int currentIndex = 0;
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
TabController _tabController;
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
_tabController.addListener(_handleTabControllerTick);
}
void _handleTabControllerTick() {
setState(() {
currentIndex = _tabController.index;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text('Profile'),
),
body: CustomScrollView(
slivers: <Widget>[
SliverToBoxAdapter(
child: Container(
height: 100,
color: Colors.blueAccent,
),
),
SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 77,
maxHeight: 77,
child: TabbedNav(
tabController: _tabController,
),
),
),
SliverToBoxAdapter(
child: IndexedStack(index: currentIndex, children: [
ListPage(color: Colors.blue),
ListPage(color: Colors.red),
ListPage(color: Colors.green),
]),
)
],
),
),
);
}
}
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate({
@required this.minHeight,
@required this.maxHeight,
@required this.child,
});
final double minHeight;
final double maxHeight;
final Widget child;
@override
double get minExtent => minHeight;
@override
double get maxExtent => math.max(maxHeight, minHeight);
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return SizedBox.expand(child: child);
}
@override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
class TabbedNav extends StatefulWidget {
final TabController tabController;
TabbedNav({Key key, this.tabController}) : super(key: key);
@override
_TabbedNavState createState() => _TabbedNavState();
}
class _TabbedNavState extends State<TabbedNav> {
final List tabs = ['One', 'Two', 'Three'];
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Material(
color: Colors.white,
child: TabBar(
indicatorColor: Colors.purpleAccent,
labelColor: Color(0xFF3C3A3A),
unselectedLabelColor: Color(0x8C3C3A3A),
controller: widget.tabController,
tabs: tabs.map((e) => Tab(text: e)).toList(),
),
),
],
);
}
}
class ListPage extends StatelessWidget {
const ListPage({Key key, this.color}) : super(key: key);
final MaterialColor color;
@override
Widget build(BuildContext context) {
const List<int> shades = <int>[
50,
100,
200,
300,
400,
500,
600,
700,
800,
900
];
return ListView.builder(
shrinkWrap: true,
itemCount: shades.length,
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 128,
child: Card(
color: color[shades[index]].withOpacity(0.75),
),
);
},
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment