Implement customized scrolling in your Flutter App
Do you want to implement custom scrolling in your Flutter application where you can position specific widgets at the top of your device like this?
It's really easy to implement using CustomScrollView.
First, create a new project using flutter create project_name
Now, open it in your desired code editor. Navigate to the lib folder and copy the following content into your main.dart file.
import 'package:custom_scroll/home_page.dart';
import 'package:flutter/material.dart';
void main(){
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: "custom scroll",
home: HomePage(),
);
}
}
Now, create a new file named home_page.dart inside your lib folder and copy the following block of code inside that file.
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Widget horizontalList() {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
"First",
"Second",
"Third",
"Fourth",
"Fifth",
"Sixth",
"Seventh",
]
.map((e) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Chip(
label: Text(e.toString()),
),
))
.toList(),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: horizontalList(),
),
SliverAppBar(
title: horizontalList(),
pinned: true,
titleSpacing: 0,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
),
SliverToBoxAdapter(
child: horizontalList(),
),
SliverAppBar(
title: horizontalList(),
pinned: true,
titleSpacing: 0,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
),
SliverToBoxAdapter(
child: ListView.separated(
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: ((context, index) => const SizedBox(
height: 5,
),
),
shrinkWrap: true,
itemCount: 50,
itemBuilder: (context, index) {
return Container(
height: 50,
alignment: Alignment.center,
color: Colors.yellow,
width: double.infinity,
child: Text("$index"),
);
},
),
)
],
),
);
}
}
Great! We've just implemented the scrolling displayed above in the embedded video.
Let me explain a few points:
The widget you want to pin must be contained in a SliverAppBar as the SliverAppBar contains a pinned property, that helps you to pin/unpin specific widgets as per your choice.
The other normally used widgets such as Container, ListView, Column, etc must be wrapped by SliverAppBar/SliverFillRemaining/SliverToBoxAdapter or something else which I currently don't know of, otherwise, you might encounter an error telling:
A RenderViewport expected a child of type RenderSliver but received a child of type RenderRepaintBoundary.
With these points in mind, you can make this effect in just a few minutes. The source code is available at: https://github.com/ankeet7x/custom_scroll
P.S. This is a way I implement it. If you guys know of some other ways, feel free to advice. Thanks :)