I am trying to implement collapsing toolbar in my app using SliverApp bar, but the problem is that the SliverAppBar is overlapping my content when the SliverAppBar is collapsed, I am attaching the gif for more understanding,
the content in the green background is going under the toolbar, I want to avoid that, any leads are appreciated.
#override
Widget build(BuildContext context) {
// TODO: implement buildr
var _tabs = {"1", "2", "3"};
return Scaffold(
backgroundColor: Colors.white,
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverOverlapAbsorber(
handle:
NestedScrollView.sliverOverlapAbsorberHandleFor(context),
child: SliverAppBar(
expandedHeight: 250.0,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
background: Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
image: DecorationImage(
fit: BoxFit.fill,
image: CachedNetworkImageProvider(
newsPost.photos[0].url),
),
),
)),
forceElevated: innerBoxIsScrolled,
))
];
},
body: SafeArea(
top: false,
bottom: false,
child: Builder(
builder: (BuildContext context) {
return CustomScrollView(
slivers: <Widget>[
SliverOverlapInjector(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
context),
),
SliverPadding(
padding: const EdgeInsets.all(8.0),
sliver: SliverFillRemaining(child: _getBody()),
),
],
);
},
),
)),
);
}
SliverAppBar Creates a material design app bar that can be placed in a NestedScrollView. Both combinly help us in achieving parallax scrolling.
SafeArea(
child: Scaffold(
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
expandedHeight: 240.0,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
title: Text(
"App Bar",
),
background: Image.network(
"https://images.pexels.com/photos/4148020/pexels-photo-4148020.jpeg",
fit: BoxFit.cover,
)),
),
];
},
body: Center(
child: Text("Hello World!!!"),
),
),
),
);
I think you should use SliverList instead of SliverFillRemaining.
body: SafeArea(
top: false,
bottom: false,
child: Builder(
builder: (BuildContext context) {
return CustomScrollView(
shrinkWrap: true,
slivers: <Widget>[
SliverOverlapInjector(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
context),
),
SliverPadding(
padding: const EdgeInsets.all(0.0),
sliver: SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return Text('Lorem ipsum dolor sit');
}, childCount: 1),
),
),
],
);
},
),
)
Related
How do I remove the space below a SliverAppBar above the body? I know it is the SliverAppBar causing the space because the padding only gets removed when I remove that:
Widget buildScrollable(BuildContext context) {
return Scaffold(
body: NestedScrollView(
controller: _scrollController,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
SliverPadding(
padding: EdgeInsets.zero,
sliver: SliverAppBar(
toolbarHeight: widget.toolbarHeight ?? _appBarHeight,
systemOverlayStyle: SystemUiOverlayStyle.dark,
brightness: Brightness.light,
actions: [
Container(
width: widget.leadingWidth ?? APP_BAR_LEADING_WIDTH,
)
],
leading: Padding(
padding: const EdgeInsets.only(left: STANDARD_PAD),
child: widget.leading),
leadingWidth: widget.leadingWidth ?? APP_BAR_LEADING_WIDTH,
centerTitle: true,
title: BlMeasureSize(
onChange: (size) {
setState(() {
_appBarHeightOrNull =
size.height < APP_BAR_MIN_HEIGHT
? APP_BAR_MIN_HEIGHT
: size.height;
});
},
child: widget.title),
pinned: false,
stretch: true,
flexibleSpace: FlexibleSpaceBarSettings(
toolbarOpacity: 1,
currentExtent: _appBarHeight,
maxExtent: _appBarHeight,
minExtent: _appBarHeight,
child: FlexibleSpaceBar(
background: Container(
decoration: const BoxDecoration(
gradient: edenYellowGradient,
),
))),
bottom: widget.bottom,
))
];
},
physics: ClampingScrollPhysics(),
body: Builder(
builder: ((context) {
_scrollController.addListener(_scrollListener);
return Stack(children: [
SlideTransition(
position: _offsetAnimation,
child: Container(
height: _appBarHeight,
decoration: const BoxDecoration(
gradient: edenYellowGradient,
),
)),
SafeArea(child: widget.body)
]);
}),
)),
);
}
I've tried SliverPadding, ClampingScrollPhysics and PreferredSize. I can't do MediaQuery.removePadding because it disables the SafeArea.
I am newbie and I am still trying to get Widgets and wrapping concept. For me it is probably hardest part of to learn Flutter.
I have Sliver AppBar and I have to get fetch some data and using FutureBuilder. Here is code
#override
Widget build(BuildContext context) => Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
backgroundColor: Colors.red,
expandedHeight: 200,
floating: true,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
background: Image.network(
'https://source.unsplash.com/random?monochromatic+dark',
fit: BoxFit.cover,
),
title: Text('Flexible Title'),
centerTitle: true,
),
//title: Text('My App Bar'),
leading: Icon(Icons.arrow_back),
actions: [
Icon(Icons.settings),
SizedBox(width: 12),
],
),
],
),
);
}
so my problem is how can I integrate my FutureBuilder snippet to this code.
Here is FutureBuilder:
FutureBuilder<Article>(
future: _futureArticle,
builder: (BuildContext context, AsyncSnapshot<Article> snapshot) {
if (snapshot.hasData) {
final article = snapshot.data?.data;
any help
The correct wrapping:
Widget build(BuildContext context) => Scaffold(
body: FutureBuilder<Article>(
future: _futureArticle,
builder: (BuildContext context, AsyncSnapshot<Article> snapshot) {
if (snapshot.hasData) {
final article = snapshot.data?.data;
return CustomScrollView(
slivers: [
SliverAppBar(
// backgroundColor: Colors.red,
expandedHeight: 200,
floating: true,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
background: Image.network(article == null
? 'https://www.tonymacx86.com/attachments/2019-02-05-07-50-43-jpeg.385401/'
: article.imageUrl!),
title: Text('${article!.title}'),
centerTitle: true,
),
leading: const Icon(Icons.arrow_back),
actions: const [
Icon(Icons.settings),
SizedBox(width: 12),
],
),
],
);
}
return const Center(
child: CircularProgressIndicator(),
);
},
),
);
}
I'm using NestedScrollView in order to achieve scroll show appbar gesture on myApp. Not sure what could be the issue, once scrolled down, doesnt show up again til you restart .
body:
NestedScrollView(
controller: _scrollController,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
sliver: SliverAppBar(
backgroundColor: Colors.red,
floating: true,
pinned: true,
toolbarHeight: 80,
automaticallyImplyLeading: false,
bottom:
PreferredSize(
preferredSize: Size.fromHeight(0),
child: new Offstage(),
),
elevation: 0,
actions: <Widget>[
// Icons
],
),
),
];
},
body:
SafeArea(
child: PageView(
controller: _pageController,
physics: NeverScrollableScrollPhysics(),
children: <Widget>[
UserListPage(),
MerchantListPage(),
],
),
),
),
Try below code hope its helpful to you. set pinned: true, inside SliverAppBar() widget refer NestedScrollView here
return Scaffold(
body: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
title: const Text('NestedScrollView'),
pinned: true,
expandedHeight: 200.0,
forceElevated: innerBoxIsScrolled,
),
];
},
body: ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: 30,
itemBuilder: (BuildContext context, int index) {
return SizedBox(
height: 50,
child: Center(child: Text('Item $index')),
);
},
),
),
);
Your result screen->
I'm creating an app where I need to implement WhatsApp like AppBar i.e to hide app bar on scroll down and show on reverse.
You can use the SliverAppBar and CustomScrollView to achieve this effect. A sample implementation:
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
pinned: false,
snap: false,
floating: false,
expandedHeight: 160.0,
flexibleSpace: const FlexibleSpaceBar(
title: Text('AppBar'),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
color: index.isOdd ? Colors.white : Colors.black12,
height: 100.0,
child: Center(
child: Text('$index', textScaleFactor: 5),
),
);
},
childCount: 50,
),
),
],
),
);
}
The glow acts like the entire screen is a list. There some way that I can put the glow below the appbar? (edit: without losing the floating effect of the appbar)
CustomScrollView(
slivers: <Widget>[
SliverAppBar(
title: Text('Home Scree'),
floating: true,
leading: Icon(Icons.alarm),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(ctx, i) {
return Column(
children: <Widget>[
ProductCard(),
Divider(
height: 0,
thickness: 1,
),
],
);
},
childCount: 10,
),
),
],
),
Maybe you can try to use NestedScrollView,like this:
#override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [SliverAppBar(
leading: Icon(Icons.alarm),
title: Text('Home Scree'),
expandedHeight: kToolbarHeight,
floating: true,
)];
},
body: ListView.builder(
padding: EdgeInsets.zero,
itemCount: 10,
itemBuilder: (context, index) {
return Column(
children: <Widget>[
ProductCard(),
Divider(
height: 0,
thickness: 1,
),
],
);
}),
),
);
}