forked from flutter/packages
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A sliver that is pinned to the start of its `CustomScrollView` and reacts to scrolling by resizing between the intrinsic sizes of its min and max extent prototypes. The minimum and maximum sizes of this sliver are defined by `minExtentPrototype` and `maxExtentPrototype`, a pair of widgets that are laid out once. You can use `SizedBox` widgets to define the size limits. This sliver is preferable to the general purpose `SliverPersistentHeader` for its relatively narrow use case because there's no need to create a `SliverPersistentHeaderDelegate` or to predict the header's minimum or maximum size. The sample shows how this sliver's two extent prototype properties can be used to create a resizing header whose minimum and maximum sizes match small and large configurations of the same header widget. https://github.com/flutter/flutter/assets/1377460/fa7ced98-9d92-4d13-b093-50392118c213 Related sliver utility PRs: flutter/flutter#143538, flutter/flutter#143196, flutter/flutter#127340.
- Loading branch information
1 parent
ea93790
commit 7e3e309
Showing
5 changed files
with
756 additions
and
0 deletions.
There are no files selected for viewing
145 changes: 145 additions & 0 deletions
145
examples/api/lib/widgets/sliver/sliver_resizing_header.0.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
// Copyright 2014 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
import 'package:flutter/material.dart'; | ||
|
||
void main() { | ||
runApp(const SliverResizingHeaderApp()); | ||
} | ||
|
||
class SliverResizingHeaderApp extends StatelessWidget { | ||
const SliverResizingHeaderApp({ super.key }); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return const MaterialApp( | ||
home: ResizingHeaderExample(), | ||
); | ||
} | ||
} | ||
|
||
class ResizingHeaderExample extends StatefulWidget { | ||
const ResizingHeaderExample({ super.key }); | ||
|
||
@override | ||
State<ResizingHeaderExample> createState() => _ResizingHeaderExampleState(); | ||
} | ||
|
||
class _ResizingHeaderExampleState extends State<ResizingHeaderExample> { | ||
late final ScrollController scrollController; | ||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
scrollController = ScrollController(); | ||
} | ||
|
||
@override | ||
void dispose() { | ||
scrollController.dispose(); | ||
super.dispose(); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
body: SafeArea( | ||
child: Padding( | ||
padding: const EdgeInsets.all(4), | ||
child: Scrollbar( | ||
controller: scrollController, | ||
child: CustomScrollView( | ||
controller: scrollController, | ||
slivers: const <Widget>[ | ||
SliverResizingHeader( | ||
minExtentPrototype: ListHeader( | ||
text: 'One', | ||
), | ||
maxExtentPrototype: ListHeader( | ||
text: 'One\nTwo\nThree' | ||
), | ||
child: ListHeader( | ||
text: 'SliverResizingHeader\nWith Two Optional\nLines of Text', | ||
), | ||
), | ||
ItemList(), | ||
], | ||
), | ||
), | ||
), | ||
), | ||
); | ||
} | ||
} | ||
|
||
// A widget that displays its text within a thick rounded rectangle border | ||
class ListHeader extends StatelessWidget { | ||
const ListHeader({ | ||
super.key, | ||
required this.text, | ||
}); | ||
|
||
final String text; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final ThemeData theme = Theme.of(context); | ||
final ColorScheme colorScheme = theme.colorScheme; | ||
|
||
return Container( | ||
color: colorScheme.background, | ||
padding: const EdgeInsets.symmetric(horizontal: 4), | ||
child: Material( | ||
color: colorScheme.primaryContainer, | ||
shape: RoundedRectangleBorder( | ||
borderRadius: BorderRadius.circular(8), | ||
side: BorderSide( | ||
width: 7, | ||
color: colorScheme.outline, | ||
), | ||
), | ||
child: Container( | ||
alignment: Alignment.center, | ||
padding: const EdgeInsets.symmetric(vertical: 16), | ||
child: Text( | ||
text, | ||
textAlign: TextAlign.center, | ||
style: theme.textTheme.headlineMedium!.copyWith( | ||
color: colorScheme.onPrimaryContainer, | ||
), | ||
), | ||
), | ||
), | ||
); | ||
} | ||
} | ||
|
||
// A placeholder SliverList of 50 items. | ||
class ItemList extends StatelessWidget { | ||
const ItemList({ | ||
super.key, | ||
this.itemCount = 50, | ||
}); | ||
|
||
final int itemCount; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final ColorScheme colorScheme = Theme.of(context).colorScheme; | ||
return SliverList( | ||
delegate: SliverChildBuilderDelegate( | ||
(BuildContext context, int index) { | ||
return Card( | ||
color: colorScheme.onSecondary, | ||
child: ListTile( | ||
textColor: colorScheme.secondary, | ||
title: Text('Item $index'), | ||
), | ||
); | ||
}, | ||
childCount: itemCount, | ||
), | ||
); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
examples/api/test/widgets/sliver/sliver_resizing_header.0_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright 2014 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_api_samples/widgets/sliver/sliver_resizing_header.0.dart' as example; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
|
||
void main() { | ||
testWidgets('SliverResizingHeader example', (WidgetTester tester) async { | ||
await tester.pumpWidget( | ||
const example.SliverResizingHeaderApp(), | ||
); | ||
|
||
final Finder headerMaterial = find.text('SliverResizingHeader\nWith Two Optional\nLines of Text'); | ||
final double initialHeight = tester.getSize(headerMaterial).height; | ||
|
||
await tester.drag(find.byType(CustomScrollView), const Offset(0, -200)); | ||
await tester.pumpAndSettle(); | ||
expect(tester.getSize(headerMaterial).height, lessThan(initialHeight / 2)); | ||
|
||
await tester.drag(find.byType(CustomScrollView), const Offset(0, 200)); | ||
await tester.pumpAndSettle(); | ||
expect(tester.getSize(headerMaterial).height, initialHeight); | ||
}); | ||
} |
Oops, something went wrong.