Last active
July 15, 2020 17:10
-
-
Save liyuqian/6fe7a6be4b5035bbdbdba57d3356b43d to your computer and use it in GitHub Desktop.
Demo how ScrollablePositionedList can handle big jump much faster than the default ListView
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
// Demo how ScrollablePositionedList can handle big jump much faster than its ListView counterpart at | |
// https://gist.github.com/esDotDev/792425c2cdfef947ce514b8ab70511e6 | |
import 'dart:developer'; | |
import 'package:flutter/material.dart'; | |
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; | |
class ScrollbarSpike extends StatefulWidget { | |
@override | |
_ScrollbarSpikeState createState() => _ScrollbarSpikeState(); | |
} | |
class _ScrollbarSpikeState extends State<ScrollbarSpike> { | |
static List<String> items = List.generate(10000, (index) => "List Item: $index"); | |
ItemScrollController scrollController; | |
@override | |
void initState() { | |
scrollController = ItemScrollController(); | |
super.initState(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
double scrollerWidth = 20; | |
return Stack( | |
children: <Widget>[ | |
Padding( | |
padding: EdgeInsets.only(right: scrollerWidth), | |
child: ScrollablePositionedList.builder( | |
physics: AlwaysScrollableScrollPhysics(), | |
itemCount: items.length, | |
itemScrollController: scrollController, | |
itemBuilder: (_, index) { | |
Timeline.startSync('build item $index'); | |
final t = Text(items[index]); | |
Timeline.finishSync(); | |
return t; | |
})), | |
Scrollbar(count: items.length, width: scrollerWidth, controller: scrollController) | |
], | |
); | |
} | |
} | |
class Scrollbar extends StatefulWidget { | |
final int count; | |
final double width; | |
final ItemScrollController controller; | |
Scrollbar({Key key, this.count, this.width, this.controller}) : super(key: key); | |
@override | |
_ScrollbarState createState() => _ScrollbarState(); | |
} | |
class _ScrollbarState extends State<Scrollbar> { | |
double _viewHeight = 100; | |
double _scrollProgress = 0.0; | |
@override | |
void initState() { | |
super.initState(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
double offset = _scrollProgress; | |
return LayoutBuilder( | |
builder: (_, BoxConstraints constraints) { | |
_viewHeight = constraints.maxHeight; | |
return Stack(children: <Widget>[ | |
Align( | |
alignment: Alignment(1, 1), | |
child: Container(color: Colors.red, width: widget.width, height: double.infinity), | |
), | |
Align( | |
alignment: Alignment(1, -1 + offset * 2), | |
child: GestureDetector( | |
onVerticalDragUpdate: _handleVerticalDrag, child: Container(width: widget.width, height: 40, color: Colors.green)), | |
) | |
]); | |
}, | |
); | |
} | |
void _handleVerticalDrag(DragUpdateDetails details) { | |
setState(() { | |
_scrollProgress = (_scrollProgress + details.delta.dy / _viewHeight).clamp(0, 1); | |
widget.controller.jumpTo(index: (widget.count * _scrollProgress).round()); | |
}); | |
} | |
} | |
class MyHomePage extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
home: Scaffold( | |
appBar: AppBar( | |
title: const Text('Sample Code'), | |
), | |
body: ScrollbarSpike(), | |
), | |
); | |
} | |
} | |
void main() { | |
runApp(MyHomePage()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment