Created
December 30, 2020 21:19
-
-
Save AlabasterAxe/a9e43483ea9ed6771b68cb5e9ff508c8 to your computer and use it in GitHub Desktop.
Final Step
This file contains 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'; | |
import 'package:flutter/widgets.dart'; | |
import 'common.dart'; | |
class ExplorePage extends StatefulWidget { | |
const ExplorePage({Key key}) : super(key: key); | |
@override | |
_ExplorePageState createState() => _ExplorePageState(); | |
} | |
class _ExplorePageState extends State<ExplorePage> | |
with SingleTickerProviderStateMixin { | |
TabController tc; | |
@override | |
void initState() { | |
super.initState(); | |
tc = TabController(length: 10, vsync: this); | |
} | |
Widget _getPodcastColumn(Color color) { | |
return Column(children: [ | |
getPodcastCover(color, 100), | |
SizedBox(height: 12.0), | |
Container( | |
width: 100, | |
child: | |
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ | |
Text("Podcast Title", style: TextStyle(fontSize: 16)), | |
Text("Subline", style: TextStyle(fontSize: 14, color: Colors.grey)), | |
])) | |
]); | |
} | |
Widget _getCollectionSection() { | |
TextTheme textTheme = Theme.of(context).textTheme; | |
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ | |
Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16), | |
child: Text("Lorem Ipsum dolor sit amet", style: textTheme.headline5), | |
), | |
SingleChildScrollView( | |
scrollDirection: Axis.horizontal, | |
child: Padding( | |
padding: const EdgeInsets.fromLTRB(24.0, 0, 24, 16), | |
child: Row(children: [ | |
_getPodcastColumn(Colors.red), | |
SizedBox(width: 12.0), | |
_getPodcastColumn(Colors.green), | |
SizedBox(width: 12.0), | |
_getPodcastColumn(Colors.yellow), | |
SizedBox(width: 12.0), | |
_getPodcastColumn(Colors.blue), | |
SizedBox(width: 12.0), | |
_getPodcastColumn(Colors.yellow[900]), | |
SizedBox(width: 12.0), | |
_getPodcastColumn(Colors.red), | |
SizedBox(width: 12.0), | |
_getPodcastColumn(Colors.green), | |
SizedBox(width: 12.0), | |
_getPodcastColumn(Colors.yellow), | |
SizedBox(width: 12.0), | |
_getPodcastColumn(Colors.blue), | |
SizedBox(width: 12.0), | |
_getPodcastColumn(Colors.yellow[900]), | |
]), | |
), | |
), | |
]); | |
} | |
Widget _getTabContents() { | |
return Column(children: [ | |
_getCollectionSection(), | |
getDivider(), | |
getEpisodeRow(Colors.red), | |
getDivider(), | |
getEpisodeRow(Colors.yellow), | |
getDivider(), | |
getEpisodeRow(Colors.green), | |
getDivider(), | |
_getCollectionSection(), | |
getDivider(), | |
getEpisodeRow(Colors.blue), | |
getDivider(), | |
getEpisodeRow(Colors.blue), | |
]); | |
} | |
Widget _getSliverifiedTabPage(Widget child, String name) { | |
return SafeArea( | |
top: false, | |
bottom: false, | |
child: Builder( | |
// This Builder is needed to provide a BuildContext that is | |
// "inside" the NestedScrollView, so that | |
// sliverOverlapAbsorberHandleFor() can find the | |
// NestedScrollView. | |
builder: (BuildContext context) { | |
return CustomScrollView( | |
// The "controller" and "primary" members should be left | |
// unset, so that the NestedScrollView can control this | |
// inner scroll view. | |
// If the "controller" property is set, then this scroll | |
// view will not be associated with the NestedScrollView. | |
// The PageStorageKey should be unique to this ScrollView; | |
// it allows the list to remember its scroll position when | |
// the tab view is not on the screen. | |
key: PageStorageKey<String>(name), | |
slivers: <Widget>[ | |
SliverOverlapInjector( | |
// This is the flip side of the SliverOverlapAbsorber | |
// above. | |
handle: | |
NestedScrollView.sliverOverlapAbsorberHandleFor(context), | |
), | |
SliverList(delegate: SliverChildListDelegate.fixed([child])), | |
], | |
); | |
}, | |
), | |
); | |
} | |
@override | |
Widget build(BuildContext context) { | |
ThemeData theme = Theme.of(context); | |
return NestedScrollView( | |
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { | |
return <Widget>[ | |
SliverOverlapAbsorber( | |
// This widget takes the overlapping behavior of the SliverAppBar, | |
// and redirects it to the SliverOverlapInjector below. If it is | |
// missing, then it is possible for the nested "inner" scroll view | |
// below to end up under the SliverAppBar even when the inner | |
// scroll view thinks it has not been scrolled. | |
// This is not necessary if the "headerSliverBuilder" only builds | |
// widgets that do not overlap the next sliver. | |
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), | |
sliver: SliverAppBar( | |
expandedHeight: 175, | |
pinned: true, | |
flexibleSpace: FlexibleSpaceBar( | |
stretchModes: <StretchMode>[], | |
collapseMode: CollapseMode.pin, | |
background: Column( | |
children: [ | |
AppBar( | |
leading: Icon(Icons.cast, color: Colors.grey[900]), | |
textTheme: theme.textTheme, | |
centerTitle: true, | |
backgroundColor: Colors.white, | |
elevation: 0, | |
title: Text("Explore"), | |
actions: [ | |
CircleAvatar( | |
backgroundImage: NetworkImage( | |
"https://i.pinimg.com/originals/d4/22/d7/d422d7642f00c404fdb5fea5393590a2.jpg")), | |
], | |
), | |
Padding( | |
padding: const EdgeInsets.fromLTRB(16.0, 8, 16, 16), | |
child: TextFormField( | |
decoration: const InputDecoration( | |
prefixIcon: Icon(Icons.search), | |
labelText: 'Search', | |
contentPadding: EdgeInsets.all(4), | |
enabledBorder: OutlineInputBorder( | |
borderSide: const BorderSide( | |
color: const Color(0xFFE1E0DE), | |
width: 1.0, | |
), | |
borderRadius: | |
BorderRadius.all(Radius.circular(10))), | |
), | |
), | |
), | |
], | |
), | |
), | |
centerTitle: true, | |
backgroundColor: Colors.white, | |
floating: true, | |
bottom: TabBar( | |
indicatorSize: TabBarIndicatorSize.label, | |
isScrollable: true, | |
indicatorWeight: 4, | |
controller: tc, | |
labelColor: theme.primaryColor, | |
labelStyle: theme.textTheme.bodyText1, | |
unselectedLabelColor: theme.textTheme.bodyText1.color, | |
tabs: [ | |
Tab(text: "Lorem"), | |
Tab(text: "Ipsum"), | |
Tab(text: "Dolor"), | |
Tab(text: "Sit"), | |
Tab(text: "Amet"), | |
Tab(text: "Lorem"), | |
Tab(text: "Ipsum"), | |
Tab(text: "Dolor"), | |
Tab(text: "Sit"), | |
Tab(text: "Amet"), | |
]), | |
), | |
), | |
]; | |
}, | |
body: TabBarView(controller: tc, children: [ | |
_getSliverifiedTabPage(_getTabContents(), "lorem"), | |
_getSliverifiedTabPage(_getTabContents(), "ipsum"), | |
_getSliverifiedTabPage(_getTabContents(), "dolor"), | |
_getSliverifiedTabPage(_getTabContents(), "sit"), | |
_getSliverifiedTabPage(_getTabContents(), "amet"), | |
_getSliverifiedTabPage(_getTabContents(), "lorem2"), | |
_getSliverifiedTabPage(_getTabContents(), "ipsum2"), | |
_getSliverifiedTabPage(_getTabContents(), "dolor2"), | |
_getSliverifiedTabPage(_getTabContents(), "sit2"), | |
_getSliverifiedTabPage(_getTabContents(), "amet2"), | |
])); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment