-
Notifications
You must be signed in to change notification settings - Fork 26.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[New feature] Allowing the ListView
slivers to have different extents while still having scrolling performance
#131393
Conversation
It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat (don't just cc him here, he won't see it! He's on Discord!). If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks very exciting! Thank you for putting this together!!
I am have been meaning to get to something similar, just have not had the opportunity yet. I thought this type of approach would resolve #52207
@@ -16,6 +16,9 @@ import 'viewport_offset.dart'; | |||
// CORE TYPES FOR SLIVERS | |||
// The RenderSliver base class and its helper types. | |||
|
|||
/// Called to get the item extent by the index of item. | |||
typedef ItemExtentGetter = double Function(int index); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of passing an index plus a little bit more information about the viewport?
My original thought for this was to see what folks thought of the TableSpanExtent API in the TableView (flutter/packages#4536) and maybe move that into the framework.
This section of the design document talks about it (links direct to that section): https://docs.google.com/document/d/15ecTZE1g3WeswLGFWrnEgMP6SyL6jDRdxOgPsczOcV0/edit?resourcekey=0-yNd_qFhiPjz6z2TgezWc0A#heading=h.a8uex5ucyiso
It defines multiple ways for developers to set an extent, based on the viewport, or the preceding scroll extent, or as the result of an operation, etc.
I figured if it worked well for folks (we did already test it in a usability study), we could use it here as well, making it a super class like ChildScrollExtent
or some such - names are hard. 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think of passing an index plus a little bit more information about the viewport?
What do you think of exposing the SliverConstraints
directly or just some of the key properity of viewport?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, that's a good idea! It won't communicate the information about how much the SliverList has laid out already though, since the SliverConstraints relate to the whole sliver and not its contents. What parts of SliverConstraints would be relevant to the user when building an item of the list? Definitely the viewportExtent I think. Maybe we can wrap those parts up in an object with additional info like how much extent has been laid out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have wraped some layout relation properity into SliverLayoutDimensions
and exposed it to the callback.
Will finish the test cases ASAP.
2c7c823
to
696873e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So excited about this. 😁 Thanks for the update!
/// Called to get the item extent by the index of item. | ||
typedef ItemExtentGetter = double Function(int index, SliverLayoutDimensions dimensions); | ||
|
||
/// Holds the relation dimensions of the [RenderSliver] during layout. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Holds the relation dimensions of the [RenderSliver] during layout. | |
/// Relates the dimensions of the [RenderSliver] during layout. | |
/// | |
/// Used by... |
Can add a reference to the item extent callback from sliver list / list view?
@@ -46,6 +47,9 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda | |||
/// The main-axis extent of each item. | |||
double get itemExtent; | |||
|
|||
/// The main-axis extent callback of each item. | |||
ItemExtentGetter? get itemExtentCallback => null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ItemExtentGetter? get itemExtentCallback => null; | |
ItemExtentGetter? get itemExtentBuilder => null; |
WDYT of this name?
3431ac5
to
6b46dc6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is nearly there. Thank you very much for putting this together, and for your patience. I found the issue requesting this and added it to the description.
packages/flutter/lib/src/rendering/sliver_fixed_extent_list.dart
Outdated
Show resolved
Hide resolved
} | ||
|
||
@override | ||
double get itemExtent => double.nan; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be nullable? Or maybe we can add an assertion as the body of this getter that says this should not be used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I have change it to nullable and add a assertion at the beginning of RenderSliverFixedExtentBoxAdaptor.performLayout()
assert((itemExtent != null && itemExtentBuilder == null) ||
(itemExtent == null && itemExtentBuilder != null));
assert(itemExtentBuilder != null || (itemExtent!.isFinite && itemExtent! >= 0));
packages/flutter/lib/src/widgets/sliver_explicit_extent_list.dart
Outdated
Show resolved
Hide resolved
packages/flutter/lib/src/widgets/sliver_explicit_extent_list.dart
Outdated
Show resolved
Hide resolved
/// extent in the main axis. | ||
/// * [SliverFillViewport], which sizes its children based on the | ||
/// size of the viewport, regardless of what else is in the scroll view. | ||
class SliverExplicitExtentList extends SliverMultiBoxAdaptorWidget { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, does this need to be it's own class? Would it be possible to use SliverFixedExtentList for both cases? I am curious for your thinking first, no need to change the code right now. As a developers, I wonder, what is the difference between Fixed and Explicit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have considered extending SliverFixedExtentList to support variable extent.
But I'm worried that this will break the developer's understanding of SliverFixedExtentList.
Maybe we need a better name to tell them the difference between the two.
It's really hard to name it, any suggestions? 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I'm worried that this will break the developer's understanding of SliverFixedExtentList.
I agree with you on this. Sorry if my question led to some code changes we should revert now. Let's keep SliverFixedExtent as it is, and integrate itemExtentBuilder into a new sliver like you proposed. :)
It's really hard to name it, any suggestions?
Hmmmm I agree names are hard.
What if...
- SliverFixedExtentList, uses itemExtent, one fixed extent for all children
- SliverVariedExtentList, uses itemExtentBuilder, children have extents provided by the builder
Then we can have them refer to one another for developers to choose what they would prefer to use.
As I was thinking about it this weekend, I think having separate render objects is a good idea. Keeps the code clearer, easier to follow, and maintain
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a great name : )
@@ -46,6 +47,9 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda | |||
/// The main-axis extent of each item. | |||
double get itemExtent; | |||
|
|||
/// The main-axis extent builder of each item. | |||
ItemExtentGetter? get itemExtentBuilder => null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if when null, this builder just returns itemExtent for every index by default? Maybe it could simplify the code below with if (itemExtentBuilder == null)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added some docs for this.
/// The main-axis extent builder of each item.
///
/// If this is non-null, the [itemExtent] must be null.
/// If this is null, the [itemExtent] must be non-null.
ItemExtentBuilder? get itemExtentBuilder => null;
09c96ad
to
930613a
Compare
Hello please approve |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! I am really excited for folks to have this, thank you so much for your work on this! 🎉
Thank you so much for your great work ! |
@Piinks Hi, Thank you very much for reviewing.
Hope you guys enjoyed your trip to Shanghai last week : )
Oh, by the way, I have recently been trying to introduce a caching mechanism to ListView to reduce unnecessary layout operations to further optimize its scrolling performance. I hope to find a better solution.
|
…rent extents while still having scrolling performance (flutter/flutter#131393)
…rent extents while still having scrolling performance (flutter/flutter#131393)
…rent extents while still having scrolling performance (flutter/flutter#131393)
…rent extents while still having scrolling performance (flutter/flutter#131393)
Absolutely! Meeting each other was a highlight of the trip! 🎉
This is really interesting, I would be happy to hear more if you are interested in pursuing it. I think in some cases caching could work, we could see what it looks like to give developers the option. Not sure. :) |
…rent extents while still having scrolling performance (flutter/flutter#131393)
…rent extents while still having scrolling performance (flutter/flutter#131393)
flutter/flutter@219efce...4e7a07a 2023-09-12 katelovett@google.com Remove chip tooltip deprecations (flutter/flutter#134486) 2023-09-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from 8a8ddaeecf8a to d4698c65aa8d (2 revisions) (flutter/flutter#134553) 2023-09-12 katelovett@google.com Remove deprecated TextSelectionOverlay.fadeDuration (flutter/flutter#134485) 2023-09-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from 25be03186d82 to 8a8ddaeecf8a (1 revision) (flutter/flutter#134545) 2023-09-12 engine-flutter-autoroll@skia.org Roll Packages from ef0c65e to e04ba88 (5 revisions) (flutter/flutter#134546) 2023-09-12 47866232+chunhtai@users.noreply.github.com Revert "Adds a parent scope TraversalEdgeBehavior and fixes modal rou� (flutter/flutter#134550) 2023-09-12 fluttergithubbot@gmail.com Marks Windows_android channels_integration_test_win to be unflaky (flutter/flutter#133129) 2023-09-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from 4091167e402d to 25be03186d82 (1 revision) (flutter/flutter#134536) 2023-09-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from 54175da7ba90 to 4091167e402d (1 revision) (flutter/flutter#134532) 2023-09-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from 85f3f02e5c37 to 54175da7ba90 (2 revisions) (flutter/flutter#134531) 2023-09-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from 1369ab35aaa7 to 85f3f02e5c37 (1 revision) (flutter/flutter#134519) 2023-09-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from 2f1efe5967f3 to 1369ab35aaa7 (1 revision) (flutter/flutter#134512) 2023-09-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from 4d8265cbc133 to 2f1efe5967f3 (3 revisions) (flutter/flutter#134511) 2023-09-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from ee7215553deb to 4d8265cbc133 (1 revision) (flutter/flutter#134506) 2023-09-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from 6ddee4423d2c to ee7215553deb (2 revisions) (flutter/flutter#134505) 2023-09-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from a98348946d61 to 6ddee4423d2c (1 revision) (flutter/flutter#134490) 2023-09-12 xubaolin@oppo.com [New feature] Allowing the `ListView` slivers to have different extents while still having scrolling performance (flutter/flutter#131393) 2023-09-12 engine-flutter-autoroll@skia.org Roll Flutter Engine from 8389ad914b21 to a98348946d61 (4 revisions) (flutter/flutter#134487) 2023-09-12 kouhei.seino@woven-planet.global ScaleGestureRecognizer: make pointerCount public (flutter/flutter#127310) 2023-09-11 chinmay@blend.to Fix DataTable example not being scrollable (flutter/flutter#131556) 2023-09-11 engine-flutter-autoroll@skia.org Roll Flutter Engine from 06696e768c1b to 8389ad914b21 (2 revisions) (flutter/flutter#134469) 2023-09-11 christopherfujino@gmail.com [flutter_tools] disallow -O0 for flutter build web (flutter/flutter#134185) 2023-09-11 sokolovskyi.konstantin@gmail.com Cover focus tests with leak tracking (flutter/flutter#134457) 2023-09-11 engine-flutter-autoroll@skia.org Roll Flutter Engine from 0774ddcda9b0 to 06696e768c1b (4 revisions) (flutter/flutter#134462) 2023-09-11 sokolovskyi.konstantin@gmail.com Fix memory leak in RenderAnimatedSize (flutter/flutter#133653) 2023-09-11 engine-flutter-autoroll@skia.org Roll Flutter Engine from e42fd367adcb to 0774ddcda9b0 (1 revision) (flutter/flutter#134447) 2023-09-11 engine-flutter-autoroll@skia.org Roll Flutter Engine from d593002b7159 to e42fd367adcb (1 revision) (flutter/flutter#134444) 2023-09-11 engine-flutter-autoroll@skia.org Roll Packages from aaae5ef to ef0c65e (6 revisions) (flutter/flutter#134445) 2023-09-11 engine-flutter-autoroll@skia.org Roll Flutter Engine from 2b5961cbc40d to d593002b7159 (3 revisions) (flutter/flutter#134439) 2023-09-11 polinach@google.com Mark leak: instances of OpacityLayer, created by _RenderChip, should be disposed. (flutter/flutter#134395) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC camillesimon@google.com,rmistry@google.com,stuartmorgan@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…rent extents while still having scrolling performance (flutter/flutter#131393)
Updates the long list cookbook to add `ListView.extentItemBuilder`, which was added recently for lists with extends of different sizes: flutter/flutter#131393 ## Presubmit checklist - [x] This PR doesn’t contain automatically generated corrections (Grammarly or similar). - [x] This PR follows the [Google Developer Documentation Style Guidelines](https://developers.google.com/style) — for example, it doesn’t use _i.e._ or _e.g._, and it avoids _I_ and _we_ (first person). - [x] This PR uses [semantic line breaks](https://github.com/dart-lang/site-shared/blob/main/doc/writing-for-dart-and-flutter-websites.md#semantic-line-breaks) of 80 characters or fewer.
Fixes #113431
Currently we only support specifying all slivers to have the same extent.
This patch introduces an
itemExtentBuilder
property forListView
, allowing the slivers to have different extents while still having scrolling performance, especially when the scroll position changes drastically(such as scrolling by the scrollbar or controller.jumpTo()).@Piinks Hi, Any thoughts about this? :)