Created
May 8, 2023 23:34
-
-
Save HansMuller/baa01604cf1bf955f225779252a13ab5 to your computer and use it in GitHub Desktop.
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'; | |
| class _CacheHeight extends SingleChildRenderObjectWidget { | |
| const _CacheHeight({ | |
| super.key, | |
| super.child, | |
| required this.heights, | |
| required this.index, | |
| }); | |
| final List<double?> heights; | |
| final int index; | |
| @override | |
| RenderObject createRenderObject(BuildContext context) { | |
| return _RenderCacheHeight( | |
| heights: heights, | |
| index: index, | |
| ); | |
| } | |
| @override | |
| void updateRenderObject(BuildContext context, _RenderCacheHeight renderObject) { | |
| renderObject | |
| ..heights = heights | |
| ..index = index; | |
| } | |
| } | |
| class _RenderCacheHeight extends RenderProxyBox { | |
| _RenderCacheHeight({ | |
| required List<double?> heights, | |
| required int index, | |
| }) : _heights = heights, | |
| _index = index, | |
| super(); | |
| List<double?> _heights; | |
| List<double?> get heights => _heights; | |
| set heights(List<double?> value) { | |
| if (value == _heights) { | |
| return; | |
| } | |
| _heights = value; | |
| markNeedsLayout(); | |
| } | |
| int _index; | |
| int get index => _index; | |
| set index(int value) { | |
| if (value == index) { | |
| return; | |
| } | |
| _index = value; | |
| markNeedsLayout(); | |
| } | |
| @override | |
| void performLayout() { | |
| super.performLayout(); // child!.layout(constraints, parentUsesSize: true); | |
| heights[index] = size.height; | |
| } | |
| } | |
| class BuildSlivers extends SliverChildBuilderDelegate { | |
| BuildSlivers({ | |
| required NullableIndexedWidgetBuilder builder, | |
| required this.heights, | |
| }) : super(builder, childCount: heights.length); | |
| final List<double?> heights; | |
| @override | |
| double? estimateMaxScrollOffset(int firstIndex, int lastIndex, double leadingScrollOffset, double trailingScrollOffset) { | |
| return heights.reduce((double? sum, double? height) => (sum ?? 0) + (height ?? 0))!; | |
| } | |
| } | |
| class ItemSlivers extends StatelessWidget { | |
| ItemSlivers({ | |
| super.key, | |
| required this.startColor, | |
| required this.endColor, | |
| }); | |
| static const List<double> cardHeights = <double>[ | |
| 600, 300, 800, 40, 400, 50, 80, 60, 50, 40, 40, 300, 400, 50, 800, 200, 30, | |
| 500, 80, 700, 40, 160, 50, 400, 80, 200, 500, 100, 80, 40, 200, 60 | |
| ]; | |
| final Color startColor; | |
| final Color endColor; | |
| final List<double?> heights = List.filled(cardHeights.length, null); | |
| @override | |
| Widget build(BuildContext context) { | |
| return SliverPadding( | |
| padding: const EdgeInsets.symmetric(horizontal: 8), | |
| sliver: SliverList( | |
| delegate: BuildSlivers( | |
| heights: heights, | |
| builder: (BuildContext context, int index) { | |
| return _CacheHeight( | |
| heights: heights, | |
| index: index, | |
| child: Card( | |
| color: Color.lerp(startColor, endColor, index / cardHeights.length)!, | |
| child: ListTile( | |
| textColor: Colors.white, | |
| title: Container( | |
| height: cardHeights[index], | |
| alignment: Alignment.centerLeft, | |
| child: Text('$index: ${cardHeights[index]}'), | |
| ), | |
| ), | |
| ), | |
| ); | |
| }, | |
| ), | |
| ), | |
| ); | |
| } | |
| } | |
| class SliverListDemo extends StatelessWidget { | |
| const SliverListDemo({ super.key }); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Scaffold( | |
| body: CustomScrollView( | |
| slivers: <Widget>[ | |
| ItemSlivers( | |
| startColor: Colors.yellow, | |
| endColor: Colors.green, | |
| ), | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |
| class SliverListDemoApp extends StatelessWidget { | |
| const SliverListDemoApp({ super.key }); | |
| @override | |
| Widget build(BuildContext context) { | |
| return MaterialApp( | |
| theme: ThemeData( | |
| useMaterial3: true, | |
| ), | |
| debugShowCheckedModeBanner: false, | |
| home: const SliverListDemo(), | |
| ); | |
| } | |
| } | |
| void main() { | |
| runApp(const SliverListDemoApp()); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment