I have a CustomScrollView
with a SliverAppBar
and some slivers. I want to overlay some graphics on the SliverAppBar
and have them scroll with the rest of the list.
Here's the code I've been working with:
import 'package:flutter/material.dart';
void main() async {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: SliverTest(),
);
}
}
class SliverTest extends StatefulWidget {
const SliverTest({super.key});
@override
State<SliverTest> createState() => _SliverTestState();
}
class _SliverTestState extends State<SliverTest> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: 350.0,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
background: Container(
color: Colors.yellow,
child: const Center(child: Text('My Parallax Image!')),
),
),
),
SliverToBoxAdapter(
child: Container(
height: 100,
color: Colors.blueAccent,
child: Stack(
children: [
Align(
alignment: const Alignment(0.0, -2.0),
child: Container(
width: 50,
height: 50,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
child: const Center(child: Text('Red')),
),
),
],
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
height: 50,
color: Colors.teal[100 * ((index % 8) + 1)],
child: Center(child: Text('Item #$index')),
);
},
childCount: 20,
),
),
],
),
),
);
}
}
In this setup, I want the red circle (which is currently clipped) to be drawn on top of the yellow section of the SliverAppBar
(Please note that the yellow section is just a simple placeholder for some actual images with parallax effect, and the use of a solid yellow color is merely for simplicity's sake). I've placed the red circle inside a sliver because I want it to scroll along with the rest of the list when the user interacts with the scrollable area.
Could anyone provide a simple example of how to achieve this in Flutter? I'm open to any other solutions that utilize slivers, as they provide huge convenience to the other parts of my real app. Otherwise, I'm aware that I may recreate it without utilizing the slivers. Any help would be greatly appreciated. Thanks in advance!
You might consider using a
Stack
widget to overlay the graphic on top of theSliverAppBar
. The challenge is, however, to make the graphic scroll along with theCustomScrollView
. You can try and adjust the position of the graphic in response to the scroll offset of theCustomScrollView
.Use a
NotificationListener
to listen to scroll events. Calculate the position of the graphic based on the scroll offset. Use aStack
and adjust the position of the graphic dynamically as the user scrolls.You can see the
NotificationListener
listening to scroll events and updating the_offset
variable. TheStack
widget overlays the red circle over theCustomScrollView
. And thePositioned
widget adjusts the position of the red circle based on the scroll offset.See if that would place the red circle on top of the
SliverAppBar
and make it scroll with the rest of the list.To address the requirements of having the red circle scroll along with the slivers and also appear behind the
SliverAppBar
, you can try and use aCustomScrollView
with aSliverPersistentHeader
. TheSliverPersistentHeader
will allow you to create a custom header that behaves like aSliverAppBar
but with more control over its contents and layout.So, create a
SliverPersistentHeader
that includes the yellow background and the red circle. Adjust the position of the red circle within the custom header so that it initially appears in the desired location but still scrolls with the rest of the content. By using aSliverPersistentHeader
, the red circle should naturally be placed behind theSliverAppBar
as it scrolls.The
SliverAppBar
should remain pinned at the top, and the custom header scrolls up underneath it.Check if you see the red circle scroll with the rest of the list and stay behind the
SliverAppBar
.