Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save HansMuller/baa01604cf1bf955f225779252a13ab5 to your computer and use it in GitHub Desktop.

Select an option

Save HansMuller/baa01604cf1bf955f225779252a13ab5 to your computer and use it in GitHub Desktop.
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