I'm trying to implement a layout with a non-solid background (e.g. a gradient), while using a SliverAppBar with FlexibleSpaceBar. The goal is to make the SliverAppBar transparent, so the background remains visible behind it, including in the collapsed state. The problem is that, scrolled body is visible under the appBar.
You can check out a minimal reproducible example here: git
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const Screen(),
);
}
}
class Screen extends StatefulWidget {
const Screen({super.key});
@override
State<Screen> createState() => _ScreenState();
}
class _ScreenState extends State<Screen> {
double _listTopPadding = kToolbarHeight;
@override
Widget build(BuildContext context) {
return Container(
// Add background gradient
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.amber, Colors.blue],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: Scaffold(
//Make scaffold transparent to show gradient
backgroundColor: Colors.transparent,
body: SafeArea(
child: NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) => [
SliverAppBar(
backgroundColor: Colors
.transparent, //Make appbar transparent tho show gradient
forceMaterialTransparency: true,
pinned: true,
expandedHeight: 200,
collapsedHeight: kToolbarHeight,
flexibleSpace: FlexibleSpaceBar(
titlePadding: EdgeInsets.zero,
//Add some content
title: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text('Felxible space'),
Container(
height: 1,
width: double.infinity,
color: Colors.black,
),
],
),
),
),
],
body: Padding(
padding: EdgeInsets.only(top: _listTopPadding),
child: ListView.builder(
itemBuilder: (context, index) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: double.infinity,
height: 75,
color: Colors.red,
),
),
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() {
if (_listTopPadding > 0) {
_listTopPadding = 0;
} else {
_listTopPadding = kToolbarHeight;
}
}),
),
),
);
}
}
So far, the only workaround I’ve found is adding top padding to the body content - but in the real-world scenario, this padding between the AppBar and body is not acceptable. The background should seamlessly continue behind the AppBar, both expanded and collapsed.
Pretty much a bump of flutter-in-a-customscrollview-how-to-prevent-a-scrolled-widget-from-being-draw
...but with a full code sample and, I believe, more concrete details.
What I need:
- The background (e.g. a gradient) should be fully visible behind the SliverAppBar, with no visual gap.
- No additional padding between the sliver app bar and the body.
- Body should be scrollable, and be not visible under the appBar
Any ideas how to achieve this cleanly?
extendBodyandextendBodyBehidAppBar