Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Add .separated constructor to ReorderableListView #168834

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

Open
wants to merge 24 commits into
base: master
Choose a base branch
Loading
from

Conversation

Fintasys
Copy link

@Fintasys Fintasys commented May 14, 2025

This PR introduces a .separated constructor to the ReorderableListView widget. The .separated constructor allows developers to define custom separators between the list items without the need to manually modify their list or create custom widgets. This API enhancement improves the overall usability and flexibility of ReorderableListView.

Key Changes:

  • Added a new .separated constructor to ReorderableListView.
  • Included appropriate documentation for the new constructor with usage examples.
  • Updated the relevant tests to verify the behavior of .separated functionality.
  • Ensured backward compatibility for existing constructors.

This new feature addresses the requests in issue #76706.

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Video

separated_example.mp4

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos labels May 14, 2025
@Fintasys Fintasys changed the title Add separated constructor to reorderable list Add .separated constructor to ReorderableListView May 14, 2025
@Fintasys Fintasys marked this pull request as ready for review May 15, 2025 04:29
@dkwingsmt dkwingsmt requested a review from victorsanni May 21, 2025 18:11
@@ -75,6 +76,8 @@ class ReorderableListView extends StatefulWidget {
///
/// * [ReorderableListView.builder], which allows you to build a reorderable
/// list where the items are built as needed when scrolling the list.
/// * [ReorderableListView.separated], which allows you to build a reorderable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Unrelated to this PR, but this and above (ReorderableListView.builder) should use third person instead of second person (i.e no 'you'). https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md#use-the-passive-voice-recommend-do-not-require-never-say-things-are-simple

}
final int itemIndex = index ~/ 2;
if (index.isEven) {
// It's an item
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Here and below, I'm not sure the comments add anything not already clear from the lines of code succeeding it.

// It's an item
return itemBuilder(context, itemIndex);
} else {
// It's a separator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here.

Comment on lines 272 to 274
/// When using the [ReorderableListView.separated] constructor, this is the total
/// number of children in the list, including items and separators.
/// The actual number of data items is less.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there is a separatorBuilder, is there a world where this only counts data items? or is this because a user might want separators only on certain indices?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think renaming it to childCount would make more sense? I was just following the existing naming pattern. Should itemCount be stored in the widget as well?

Comment on lines 405 to 407
/// This callback is used to build the separator widgets that appear between items.
/// It is called with indices from 0 to `itemCount - 2` (where `itemCount` is
/// the number of actual data items).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of speculating about the data items or non-data items, can we directly reference ReorderableListView.itemCount here (assuming an item-separator-item pattern)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to above question, I think it's better then to store itemCount and childCount separately and itemCount can be properly referenced here.

/// It is called with indices from 0 to `itemCount - 2` (where `itemCount` is
/// the number of actual data items).
///
/// Will be null if not using the `separated` constructor.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Will be null if not using the `separated` constructor.
/// Null if this is not a `ReorderableListView.separated`.

or something similar.

/// Will be null if not using the `separated` constructor.
final IndexedWidgetBuilder? separatorBuilder;

/// Helper method to compute the actual child count for the separated constructor.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Helper method to compute the actual child count for the separated constructor.
/// Helper method to compute the actual child count for a `ReorderableListView.separated`.

Prefer the actual reference over a (possibly) vague allusion.

Comment on lines +438 to +440
// If using .separated, separators are at odd indices.
// We only want drag handles and specific keys for actual items (even indices).
final bool isSeparator = widget.separatorBuilder != null && index.isOdd;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels odd (no pun intended). Does this break down if a user has their separators at non-regular intervals?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current implementation enforces a regular pattern where separators must appear between every item. This is by design and matches the behavior of ListView.separated. If users need non-regular separators, they should use the regular ReorderableListView or ReorderableListView.builder constructors and handle the separators manually in their item builder.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation for the constructor should contain this info if it doesn't already.

@victorsanni victorsanni requested a review from bleroux May 22, 2025 23:50
@Fintasys
Copy link
Author

@victorsanni Thanks for the detailed review ! I tried to address all of your concerns, please have another look 🙇

Comment on lines +121 to +122
itemCount = children.length,
childCount = children.length,
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Keep separated track of itemCount and childCount. itemCount is used in the default constructor and .builder constructor. .seperated constructor requires additional property childCount to keep track of combined count of items + divider.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see ListView.separated does something similar with what you had previously (using itemCount etc). I first blind-reviewed but now I see the implementation aims to be almost identical to ListView.separated.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can I confirm with you if you say I should revert my changes and exclusively use itemCount? Or is it okay to continue having separate variables for itemCount and childCount ? Later one makes technical more sense to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that childCount is defined and calculated but never used. If childCount does not modify the behavior of this widget, then it shouldn't be added.

Copy link
Contributor

@victorsanni victorsanni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for responding! Can you also attach videos/screenshots to the PR description comparing before/after? This will make the PR easier to review.

The example and tests are also really nice. For now, can you attach the example code to the PR description, and add the example/example test in a subsequent PR? The leaner the PR, the easier it is to review.

Thanks once again.

Comment on lines +121 to +122
itemCount = children.length,
childCount = children.length,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see ListView.separated does something similar with what you had previously (using itemCount etc). I first blind-reviewed but now I see the implementation aims to be almost identical to ListView.separated.

Comment on lines +438 to +440
// If using .separated, separators are at odd indices.
// We only want drag handles and specific keys for actual items (even indices).
final bool isSeparator = widget.separatorBuilder != null && index.isOdd;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation for the constructor should contain this info if it doesn't already.

@@ -143,7 +148,7 @@ class ReorderableListView extends StatefulWidget {
/// {@end-tool}
/// See also:
///
/// * [ReorderableListView], which allows you to build a reorderable
/// * [ReorderableListView], which allows one to build a reorderable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// * [ReorderableListView], which allows one to build a reorderable
/// * [ReorderableListView], which builds a reorderable

Or something similar. But this is a nit, feel free to edit.

/// number of children in the list, including items and separators.
/// When using [ReorderableListView] or the [ReorderableListView.builder] constructor, this is the number of items
/// in the list.
final int childCount;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think this property should be added.

Comment on lines 272 to 275
/// The number of data items in the list.
///
/// This is the number of data items in the list, not the number of children.
/// For example, if there is a list with 10 items and 9 separators, this will be 10.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is custom, then the macro should be removed. You can combine the information in here with what the macro already has with something like this:

  /// The number of data items in the list.
  ///
  /// If this widget is a ReorderableListView.separated, {insert docs for special case}
  ///
  /// This value must be a non-negative integer. When zero, nothing is displayed and
  /// the widget occupies no space.

final double? itemExtent;

/// {@macro flutter.widgets.list_view.itemExtentBuilder}
/// This is not used by the [ReorderableListView.separated] constructor.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// This is not used by the [ReorderableListView.separated] constructor.
///
/// Null if this is a [ReorderableListView.separated].

final ItemExtentBuilder? itemExtentBuilder;

/// {@macro flutter.widgets.list_view.prototypeItem}
/// This is not used by the [ReorderableListView.separated] constructor.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// This is not used by the [ReorderableListView.separated] constructor.
///
/// Null if this is a [ReorderableListView.separated].

Comment on lines +419 to +422
/// Helper method to compute the actual child count for [ReorderableListView.separated].
static int _computeActualChildCount(int itemCount) {
return math.max(0, itemCount * 2 - 1);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this method is needed or used.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is needed to calculate the total child length based on amount of items and the necessary dividers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method is only used here to calculate childCount, but childCount is never used as far as I can see. Could I be missing something?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You suggest to remove childCount and consolidate it with itemCount. For calculation of itemCount we would still need the method to properly count the total items (items + divider count). Am I completely misunderstanding what you mean?
Or do you mean it is not necessary to combine divider count + item count into itemCount so that itemCount should just be the number of items (exclusive dividers). I didn't consider that so far, cause I'm not sure if it plays internally a role.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I searched in this file for childCount. I saw it was added as a property, and it was also updated here:

childCount = _computeActualChildCount(itemCount),

but I can't find where it is actually used/referenced.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You suggest to remove childCount and consolidate it with itemCount. For calculation of itemCount we would still need the method to properly count the total items (items + divider count). Am I completely misunderstanding what you mean?

If the method is needed to calculate itemCount, then it should be used to do that. But right now I don't see it being used to calculate itemCount, only childCount.

packages/flutter/lib/src/widgets/reorderable_list.dart Outdated Show resolved Hide resolved
packages/flutter/lib/src/material/reorderable_list.dart Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.