Created
December 28, 2021 01:53
Revisions
-
diegoveloper created this gist
Dec 28, 2021 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,145 @@ class DiegoveloperDataTable extends StatefulWidget { const DiegoveloperDataTable({Key? key}) : super(key: key); @override State<DiegoveloperDataTable> createState() => _DiegoveloperDataTableState(); } const itemWidth = 120.0; final itemsHeader = List.generate( 10, (index) => SizedBox(width: itemWidth, child: Text('Header $index'))); class _DiegoveloperDataTableState extends State<DiegoveloperDataTable> { final _controllerHorizontalHeader = CustomScrollController(); final _controllerHorizontalBody = CustomScrollController(); void _listenScrollHeader() { _controllerHorizontalBody.jumpToWithoutGoingIdleAndKeepingBallistic( _controllerHorizontalHeader.offset); } void _listenScrollBody() { _controllerHorizontalHeader.jumpToWithoutGoingIdleAndKeepingBallistic( _controllerHorizontalBody.offset); } @override void initState() { _controllerHorizontalHeader.addListener(_listenScrollHeader); _controllerHorizontalBody.addListener(_listenScrollBody); super.initState(); } @override void dispose() { _controllerHorizontalHeader.removeListener(_listenScrollHeader); _controllerHorizontalBody.removeListener(_listenScrollBody); _controllerHorizontalHeader.dispose(); _controllerHorizontalBody.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( slivers: [ const SliverToBoxAdapter( child: Card( child: Center( child: FlutterLogo( size: 300, ), ), ), ), SliverAppBar( title: SingleChildScrollView( controller: _controllerHorizontalHeader, scrollDirection: Axis.horizontal, child: Row( children: itemsHeader, ), ), pinned: true, ), SliverToBoxAdapter( child: SingleChildScrollView( controller: _controllerHorizontalBody, scrollDirection: Axis.horizontal, child: Column( children: List.generate( 20, (index) => Row( children: List.generate( itemsHeader.length, (index) => SizedBox( width: itemWidth, child: ListTile( title: Text('Item :$index'), ), ), ), ), ), ), ), ) ], ), ); } } class CustomScrollController extends ScrollController { CustomScrollController({ double initialScrollOffset = 0.0, bool keepScrollOffset = true, String? debugLabel, }) : super( initialScrollOffset: initialScrollOffset, keepScrollOffset: keepScrollOffset, debugLabel: debugLabel); @override _SilentScrollPosition createScrollPosition( ScrollPhysics physics, ScrollContext context, ScrollPosition? oldPosition, ) { return _SilentScrollPosition( physics: physics, context: context, oldPosition: oldPosition, initialPixels: initialScrollOffset, ); } void jumpToWithoutGoingIdleAndKeepingBallistic(double value) { assert(positions.isNotEmpty, 'ScrollController not attached.'); for (_SilentScrollPosition position in List<ScrollPosition>.from(positions) .whereType<_SilentScrollPosition>()) { position.jumpToWithoutGoingIdleAndKeepingBallistic(value); } } } class _SilentScrollPosition extends ScrollPositionWithSingleContext { _SilentScrollPosition({ required ScrollPhysics physics, required ScrollContext context, ScrollPosition? oldPosition, double? initialPixels, }) : super( physics: physics, context: context, oldPosition: oldPosition, initialPixels: initialPixels, ); void jumpToWithoutGoingIdleAndKeepingBallistic(double value) { if (pixels != value) { forcePixels(value); } } }