-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Closed
Labels
P1High-priority issues at the top of the work listHigh-priority issues at the top of the work listc: regressionIt was better in the past than it is nowIt was better in the past than it is nowf: material designflutter/packages/flutter/material repository.flutter/packages/flutter/material repository.f: scrollingViewports, list views, slivers, etc.Viewports, list views, slivers, etc.found in release: 3.32Found to occur in 3.32Found to occur in 3.32found in release: 3.33Found to occur in 3.33Found to occur in 3.33frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team
Description
Steps to reproduce
- Run the provided minimal Flutter project or code sample.
- Scroll down slowly through the list until you reach the last items of any group.
- Observe how the pinned header behaves as the last item approaches the top of the screen.
✅ Note: This issue only occurs on Flutter 3.32+. It worked correctly in Flutter 3.29.
Expected results
When scrolling a long list grouped with SliverMainAxisGroup and PinnedHeaderSliver, the pinned header should remain fixed at the top until the next header scrolls in and replaces it.
The last list item should not push the header early. The header should only be replaced when the scroll reaches the next header.
Actual results
In Flutter 3.32, using SliverMainAxisGroup with PinnedHeaderSliver causes the header to be pushed too early when reaching the last item of the list.
This behavior did not happen in Flutter 3.29, where the sticky header was behaving as expected.
Code sample
Code sample
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 Bug',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Sliver MainAxis Group Bug'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<_Group> groupedItems = [
_Group(name: 'Owned', items: List.generate(4, (_) => _MyItem())),
_Group(name: 'Wishlist', items: List.generate(5, (_) => _MyItem())),
_Group(name: 'Recently Played', items: List.generate(3, (_) => _MyItem())),
_Group(name: 'Recently Added', items: List.generate(4, (_) => _MyItem())),
_Group(name: 'Recently Updated', items: List.generate(6, (_) => _MyItem())),
_Group(name: 'Recently Played', items: List.generate(2, (_) => _MyItem())),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue,
title: Text(widget.title),
),
body: CustomScrollView(
slivers: [
const SliverPadding(padding: EdgeInsets.only(top: 4)),
for (final group in groupedItems)
SliverMainAxisGroup(
key: ValueKey(group),
slivers: [
PinnedHeaderSliver(
child: _MyHeaderListItem(group: group.name),
),
SliverPrototypeExtentList.builder(
// Prevents the sliverList items from being kept in memory when they are not visible.
addAutomaticKeepAlives: false,
prototypeItem: _MyItem(),
itemBuilder: (context, index) => _MyItem(),
itemCount: group.items.length,
),
],
)
],
),
);
}
}
class _Group {
final String name;
final List<dynamic> items;
_Group({required this.name, required this.items});
}
class _MyHeaderListItem extends StatelessWidget {
const _MyHeaderListItem({required this.group});
final String group;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(12),
child: Container(
decoration: BoxDecoration(
gradient: const LinearGradient(colors: [Colors.blueGrey, Colors.lightBlue]),
borderRadius: BorderRadius.circular(20),
),
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
child: Text(group, style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold)),
),
);
}
}
class _MyItem extends StatelessWidget {
const _MyItem();
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.blueGrey[300],
borderRadius: BorderRadius.circular(12),
boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 4, offset: const Offset(0, 2))],
),
child: InkWell(
onTap: () => {},
child: Row(
children: [
Container(
width: 60,
height: 90,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8),
),
),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('🎏 Lorem ipsum dolor', maxLines: 1, overflow: TextOverflow.ellipsis),
const SizedBox(height: 4),
Text('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.black54)),
],
),
),
],
),
),
);
}
}Screenshots or Video
Logs
Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.32.7, on macOS 15.3 24D60 darwin-x64, locale es-ES)
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 16.2)
[✓] Android Studio (version 2021.3)
[✓] Android Studio (version 2023.3)
[✓] VS Code (version 1.102.3)
[✓] Connected device (4 available)
[✓] Network resourcestirth-patel-nctirth-patel-nc
Metadata
Metadata
Assignees
Labels
P1High-priority issues at the top of the work listHigh-priority issues at the top of the work listc: regressionIt was better in the past than it is nowIt was better in the past than it is nowf: material designflutter/packages/flutter/material repository.flutter/packages/flutter/material repository.f: scrollingViewports, list views, slivers, etc.Viewports, list views, slivers, etc.found in release: 3.32Found to occur in 3.32Found to occur in 3.32found in release: 3.33Found to occur in 3.33Found to occur in 3.33frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamOwned by Framework teamtriaged-frameworkTriaged by Framework teamTriaged by Framework team
