Last active
October 28, 2020 03:15
-
-
Save tranductam2802/30c4b4dcdb2b6673e28327e17d2a3bee to your computer and use it in GitHub Desktop.
Demo auto hide header of the scroll view
This file contains hidden or 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
import 'package:flutter/material.dart'; | |
import 'package:flutter/rendering.dart'; | |
void main() { | |
runApp(App()); | |
} | |
class App extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
home: MyWidget(), | |
); | |
} | |
} | |
class MyWidget extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
final headerHeight = 200.0; | |
final controller1 = ScrollController(initialScrollOffset: headerHeight); | |
final controller2 = ScrollController(initialScrollOffset: headerHeight); | |
final controller3 = ScrollController(initialScrollOffset: headerHeight); | |
return Scaffold( | |
body: Column( | |
children: [ | |
Container( | |
height: 700, | |
child: Row( | |
children: [ | |
Expanded( | |
child: Container( | |
child: CustomScrollView( | |
controller: controller1, | |
slivers: <Widget>[ | |
SliverPersistentHeader( | |
pinned: true, | |
delegate: HideHeader(headerHeight: headerHeight), | |
), | |
SliverList( | |
delegate: SliverChildBuilderDelegate( | |
(BuildContext context, int index) { | |
return Container( | |
height: 50, | |
color: | |
index % 2 == 0 ? Colors.amber : Colors.black, | |
); | |
}, | |
childCount: 12, | |
), | |
), | |
SliverFillRemainingHideHeader( | |
headerHeight: headerHeight, | |
), | |
], | |
), | |
), | |
), | |
Expanded( | |
child: Container( | |
child: CustomScrollView( | |
controller: controller2, | |
slivers: <Widget>[ | |
SliverPersistentHeader( | |
pinned: true, | |
delegate: HideHeader(headerHeight: headerHeight), | |
), | |
SliverList( | |
delegate: SliverChildBuilderDelegate( | |
(BuildContext context, int index) { | |
return Container( | |
height: 50, | |
color: | |
index % 2 == 0 ? Colors.amber : Colors.black, | |
); | |
}, | |
childCount: 14, | |
), | |
), | |
SliverFillRemainingHideHeader( | |
headerHeight: headerHeight, | |
), | |
], | |
), | |
), | |
), | |
Expanded( | |
child: Container( | |
child: CustomScrollView( | |
controller: controller3, | |
slivers: <Widget>[ | |
SliverPersistentHeader( | |
pinned: true, | |
delegate: HideHeader(headerHeight: headerHeight), | |
), | |
SliverList( | |
delegate: SliverChildBuilderDelegate( | |
(BuildContext context, int index) { | |
return Container( | |
height: 50, | |
color: | |
index % 2 == 0 ? Colors.amber : Colors.black, | |
); | |
}, | |
childCount: 16, | |
), | |
), | |
SliverFillRemainingHideHeader( | |
headerHeight: headerHeight, | |
), | |
], | |
), | |
), | |
), | |
], | |
), | |
), | |
Expanded( | |
child: Container( | |
color: Colors.green, | |
), | |
), | |
], | |
), | |
); | |
} | |
} | |
class SliverFillRemainingHideHeader extends SingleChildRenderObjectWidget { | |
const SliverFillRemainingHideHeader({Key key, this.headerHeight = 0.0}) | |
: super(key: key); | |
final double headerHeight; | |
@override | |
RenderSliverFillRemainingHideHeader createRenderObject( | |
BuildContext context) => | |
RenderSliverFillRemainingHideHeader(headerHeight: headerHeight); | |
} | |
class RenderSliverFillRemainingHideHeader extends RenderSliverSingleBoxAdapter { | |
RenderSliverFillRemainingHideHeader( | |
{RenderBox child, this.headerHeight = 0.0}) | |
: super(child: child); | |
final double headerHeight; | |
@override | |
void performLayout() { | |
final viewportExtent = constraints.viewportMainAxisExtent; | |
final scrollExtent = constraints.precedingScrollExtent; | |
double extent = viewportExtent - scrollExtent; | |
if (extent > -headerHeight) { | |
extent += headerHeight; | |
} | |
if (extent < 0.0) { | |
extent = 0.0; | |
} | |
assert(extent.isFinite); | |
final double paintedChildSize = | |
calculatePaintOffset(constraints, from: 0.0, to: extent); | |
assert(paintedChildSize.isFinite); | |
assert(paintedChildSize >= 0.0); | |
geometry = SliverGeometry( | |
scrollExtent: extent, | |
paintExtent: paintedChildSize, | |
maxPaintExtent: paintedChildSize, | |
hasVisualOverflow: extent > constraints.remainingPaintExtent || | |
constraints.scrollOffset > 0.0, | |
); | |
} | |
} | |
class HideHeader extends SliverPersistentHeaderDelegate { | |
HideHeader({this.headerHeight}); | |
final double headerHeight; | |
@override | |
Widget build(context, shrinkOffset, overlapsContent) => | |
Container(color: Colors.blue); | |
@override | |
bool shouldRebuild(SliverPersistentHeaderDelegate _) => true; | |
@override | |
double get maxExtent => headerHeight; | |
@override | |
double get minExtent => 0.0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment