Nested SliverPersistentHeaders scroll behind parent SliverPersistentHeader - flutter

So i would like to have a page with first some content, then two tabs with two different lists. The Tab bar should behave like a PersistentHeader (sticking to the top). One of these Lists within the TabBarView also contains SliverPersistentHeaders but these do not stack up on the TabBar PersistentHeader but scroll behind instead. How can one achieve such behaviour?
Here's a gif that shows the current behaviour:
This is what i've tried so far:
#override
Widget build(BuildContext context) {
return NestedScrollView(
controller: _scrollViewController,
headerSliverBuilder:
(BuildContext context, bool boxIsScrolled) {
return <Widget>[
SliverList(
delegate: SliverChildListDelegate([
_buildTopImage(),
Padding(
padding: EdgeInsets.symmetric(
horizontal: defaultPagePadding),
child: _buildTopText(),
),
]),
),
SliverAppBar(
pinned: true,
floating: true,
expandedHeight: 0,
backgroundColor: Colors.white,
bottom: TabBar(
labelColor: Theme.of(context).primaryColor,
unselectedLabelColor: Colors.grey,
tabs: <Widget>[
Tab(
text: "Tab 1",
),
Tab(
text: "Tab 2",
)
],
controller: _tabController,
),
)
];
},
body: TabBarView(
children: <Widget>[
_buildList1(),
_buildList2(),
],
controller: _tabController,
),
),
}
Widget _buildList2() {
return CustomScrollView(slivers: <Widget>[
SliverAppBar(
pinned: true,
title: Text('Test'),
),
SliverAppBar(
pinned: true,
title: Text('Test'),
),
SliverAppBar(
pinned: true,
title: Text('Test'),
),
]);
}
I'm new to Flutter so i would really appreciate any help from you guys!

Related

How to customize tabs in appbar?

I am developing a flutter app, in home screen i have tabs( each tab is showing a category) and by click one of them the category products will appear.
Just like that
The problem is when i click home first i must have a general products from all categories and no category should be selected first.
After the user see's the general products he can then choose category he wants to see.
So i must customize the tabs and i don't know how.
Any idea?
Here is a demo widget using DefaultTabController, you can archive it easily.
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 4,
child: Scaffold(
body: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (context, innerBoxIsScrolled) => [
SliverAppBar(
snap: true,
floating: true,
toolbarHeight: 80,
backgroundColor: Colors.white,
title: Container(
width: double.infinity,
color: Colors.redAccent,
child: Text("search here"),
),
centerTitle: true,
bottom: PreferredSize(
preferredSize: Size(0.0, 48.0),
child: Column(
children: [
TabBar(
isScrollable: true,
indicatorWeight: 1,
labelColor: Colors.green,
unselectedLabelColor: Colors.grey,
// indicatorSize: TabBarIndicatorSize.label,
labelStyle: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16.0,
),
tabs: [
Tab(text: "screen1"),
Tab(text: "screen2"),
Tab(text: "screen3"),
Tab(text: "screen4"),
],
),
],
),
),
)
],
body: TabBarView(
children: [
Container(
child: Text("screen1"),
),
Container(
child: Text("screen2"),
),
Container(
child: Text("screen3"),
),
Container(
child: Text("screen4"),
),
],
)),
),
);
}
}

Flutter remove the space TabBar and SliverAppBar

I want to implement a float AppBar with a pinned TabBar at the bottom. The following is the test code (dartPad):
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
backgroundColor: Colors.yellow,
title: Text(
"WhatsApp type sliver appbar",
),
centerTitle: true,
pinned: true,
floating: true,
bottom: PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: Container(
color: Colors.orange,
alignment: Alignment.topLeft,
child: TabBar(
isScrollable: true,
indicatorColor: Colors.white,
indicatorSize: TabBarIndicatorSize.label,
controller: _tabController,
labelPadding: EdgeInsets.only(
top: 13, bottom: 13, left: 16, right: 16),
tabs: [
Text(
"TAB A",
),
Text(
"TAB B",
),
]),
),
),
),
];
},
body: TabBarView(
controller: _tabController,
children: [
TabA(),
const Center(
child: Text('Display Tab 2',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
),
],
),
),
);
}
I find that it will have a top-padding on the TabBar when scrolling down. Is there any way to remove that space? I have set the SliverAppBar's toolbarheight, but that space will keep there even I lower the height.
scroll up (show appbar):
scroll down (hide appbar, the top yellow is not hidden):
Just set property pinned: false
See documentation
pinned → bool
Whether the app bar should remain visible at the start of the scroll view. [...]
final
Also remove tabBar from bottom: and add it above tabbarview inside a column
Thank you for the help.
Finally, I have another solution that may also take consider. I post here for others to ref.
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
backgroundColor: Colors.yellow,
title: Text(
"WhatsApp type sliver appbar",
),
elevation: 0.0,
forceElevated: false,
pinned: false,
floating: true,
primary: false,
centerTitle: false,
titleSpacing: NavigationToolbar.kMiddleSpacing,
automaticallyImplyLeading: false,
),
SliverAppBar(
backgroundColor: Colors.orange,
pinned: true,
primary: false,
centerTitle: false,
titleSpacing: 0,
toolbarHeight: 48,
automaticallyImplyLeading: false,
forceElevated: true,
title: Align(
alignment: Alignment.topLeft,
child: TabBar(
isScrollable: true,
indicatorColor: Colors.white,
indicatorSize: TabBarIndicatorSize.label,
controller: _tabController,
labelPadding: EdgeInsets.only(
top: 13, bottom: 13, left: 16, right: 16),
tabs: [
Text(
"TAB A",
),
Text(
"TAB B",
),
]),
),
),
];
},
body: TabBarView(
controller: _tabController,
children: [
TabA(),
const Center(
child: Text('Display Tab 2',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
),
],
),
),
);
}
Basically, what i do is separate 2 SliverAppBar, one is not pinned and floating; another is pinned. This makes the upper appbar disappear when scroll down and display when scroll up while the tabbar will keep pinning there.
İf you use listview add this line
ListView.builder(
padding: EdgeInsets.zero,

Flutter - How to add custom tabbar inside sliverappbar?

I'm trying to implement a custom tab bar widget inside a SliverAppBar. So far I've tried wrapping my CustomTabBar within a PreferredSize widget.
Here's my code:
Widget _buildBody(){
return NestedScrollView(
headerSliverBuilder: (BuildContext context, bool boxIsScrolled) {
return <Widget>[
SliverAppBar(
leading: Container(),
backgroundColor: Colors.transparent,
expandedHeight: 200.0,
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.pin,
background: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(
"Item 1"
),
Text(
"Item 2"
),
Text(
"Item 3"
)
],
)
]),
),
bottom: PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: CustomTabWidget(
items: ['Challenge', 'My friends'],
activeColor: secondaryColor,
currentIndex: currentIndex,
backgroundColor: tabColor,
activeTextColor: Colors.white,
backgroundTextColor: Colors.white,
onTabSelect: (int index) {
onLeaderboardTabSelect(index);
},
),
),];
},
body: ListView.separated(
itemCount: 50,
itemBuilder: (context, index) {
return ListTile(
title: Text('row $index'),
);
},
separatorBuilder: (context, index) {
return Divider();
},
) // should return listview depending on the tab
);
}
CustomTabWidget
Widget build(BuildContext context) {
return Container(
height: height,
decoration: BoxDecoration(
color: backgroundColor,
borderRadius: BorderRadius.circular(
30.0,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: _buildItems(context),
),
);
}
The code successfully shows the my custom tab bar widget but whenever I scroll down or tap another tab, it disappears.
I might have overlooked something within the code.
Can anyone help me?
this work on my project
class TabBarInSliverAppbar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
title: Text("Tabbar in SliverAppbar Example"),
pinned: true,
floating: true,
bottom: TabBar(
tabs: <Widget>[
Tab(
text: "First Tab",
),
Tab(
text: "Second Tab",
),
],
),
),
SliverToBoxAdapter(
child: TabBarView(
children: <Widget>[
Center(
child: Text("First Tab"),
),
Center(
child: Text("Second Tab"),
),
],
),
),
],
),
),
);
}
}
you can also checki this link :Flutter TabBar and SliverAppBar that hides when you scroll down

Flutter: collapsing app bar with pinned tabBar

How add build collapsing app bar with pinned tabBar in Flutter like in this GIF
I managed to build it like so
class Test extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: DefaultTabController(
length: 2,
child: NestedScrollView(
headerSliverBuilder: (context, value) {
return [
SliverAppBar(
floating: true,
pinned: true,
title: Text('Test'),
bottom: TabBar(
tabs: [
Tab( text: "Call"),
Tab( text: "Message"),
],
),
),
];
},
body: TabBarView(
children: [
Container(child: ListView.builder(
itemCount: 100,
itemBuilder: (context,index){
return Text("Item $index");
})),
Container(child: ListView.builder(
itemCount: 100,
itemBuilder: (context,index){
return Text("Item $index");
})),
],
),
),
),
);
}
}
You can use the SilverAppBar
SliverAppBar(
expandedHeight: 150.0,
floating:true,
pinned: true,
flexibleSpace: const FlexibleSpaceBar(
title: Text('Available seats'),
),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.add_circle),
tooltip: 'Add new entry',
onPressed: () { /* ... */ },
),
]
)
References
SliverAppBar Class
SliverAppBar Widget of the week
Keep the TabBarView seperate from the SliverAppBar.
Make it look continuous by setting SliverAppBar's elevation to 0 and use shadow or elevation for the TabBarView, whatever you prefer.

How to show only the TabView in a SilverAppBar

I'd basically like to have a TabView navigation in the middle of my page.
To do so I used a SliverAppBar inside a NestedScrollView.
My SliverAppBar is only composed by my TabView, I wrapped my TabView inside a SliverAppBar in order to used the pinned: true propriety.
return Scaffold(
appBar: AppBar(
title: Text('Title'),
),
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool boxIsScrolled) {
return <Widget>[
SliverToBoxAdapter(
child: Container(
height: 500,
color: Colors.red,
)),
SliverAppBar(
pinned: true,
bottom: TabBar(
tabs: <Widget>[
Tab(
text: "Home",
icon: Icon(Icons.home),
),
Tab(
text: "Example page",
icon: Icon(Icons.help),
)
],
controller: _tabController,
)),
];
},
body: TabBarView(
children: <Widget>[
PageExample(),
PageExample(),
],
controller: _tabController,
),
),
);
It does the trick, my problem is I'd like to hide/remove this SliverAppBar that wrapped my TabBar:
I needed to set expandedHeight to 0:
return Scaffold(
appBar: AppBar(
title: Text('Title'),
),
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool boxIsScrolled) {
return <Widget>[
SliverToBoxAdapter(
child: Container(
height: 500,
color: Colors.red,
)),
SliverAppBar(
expandedHeight: 0,
pinned: true,
bottom: TabBar(
tabs: <Widget>[
Tab(
text: "Home",
icon: Icon(Icons.home),
),
Tab(
text: "Example page",
icon: Icon(Icons.help),
)
],
controller: _tabController,
)),
];
},
body: TabBarView(
children: <Widget>[
PageExample(),
PageExample(),
],
controller: _tabController,
),
),
);