Skip to content

Conversation

@Piinks
Copy link
Contributor

@Piinks Piinks commented Feb 3, 2021

Design Document

This change applies Raw/Cupertino/Scrollbars by default on the Web and Desktop platforms. I've done this in a similar way to how we apply the GlowingOverscrollIndicator, in each Widget/Material/Cupertino ScrollBehavior. This allows us to get the right Scrollbar for the given ScrollBehavior.


This current proposal requires a breaking change to ScrollBehavior.buildViewportChrome, adding an optional controller parameter as Scrollbar requires a ScrollController for full functionality. Update: Instead I have deprecated buildViewportChrome in favor of buildViewportDecoration. Breaking the former was a really hard break, so I have introduced a new method, and added an opt-in flag (ScrollBehavior.useDecoration) so customers can be migrated gracefully.

This new method will use (also new) ScrollableDetails to ascertain the right decoration. Passing ScrollableDetails will be a bit more future-proof, where if needed we can add to the details rather than needing to change a function signature. The ScrollableDetails currently contains the required AxisDirection (used for the GlowingOverscrollIndicator decoration), and an optional controller. If a controller is not provided, no Scrollbar will be created.


Some instances of Scrollable are excluded from this including:

  • EditableText
  • ListWheelScrollView
  • PageView
  • NestedScrollView
  • Dropdown menus (they have their own ScrollBehavior that I have, for now, excluded scrollbars from)

To give users control over this, I have added the ability to toggle this feature on and off in ThemeData and CupertinoThemeData. Update: This was a bit over the top, exposing ScrollBehaviors is a cleaner way for users to control defaults. That will be a prerequisite change, in #76739


Blocked by: #76739

Fixes: #40107
Fixes: #70866 (Last part)
Also related as part of ScrollBehavior overhaul: #75728

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I listed at least one issue that this PR fixes in the description above.
  • I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test exempt.
  • I updated/added relevant documentation (doc comments with ///).
  • I signed the CLA.
  • All existing and new tests are passing.

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

@Piinks Piinks added c: new feature Nothing broken; request for a new capability framework flutter/packages/flutter repository. See also f: labels. c: API break Backwards-incompatible API changes f: scrolling Viewports, list views, slivers, etc. customer: crowd Affects or could affect many people, though not necessarily a specific customer. platform-web Web applications specifically a: desktop Running on desktop labels Feb 3, 2021
@flutter-dashboard flutter-dashboard bot added f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. labels Feb 3, 2021
@google-cla google-cla bot added the cla: yes label Feb 3, 2021
@Piinks
Copy link
Contributor Author

Piinks commented Feb 3, 2021

Still WIP here 🤕 😝

@Piinks Piinks removed f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. labels Feb 3, 2021
@goderbauer goderbauer marked this pull request as draft February 3, 2021 22:39
@flutter-dashboard
Copy link

This pull request has been changed to a draft. The currently pending flutter-gold status will not be able to resolve until a new commit is pushed or the change is marked ready for review again.

For more guidance, visit Writing a golden file test for package:flutter.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@Piinks
Copy link
Contributor Author

Piinks commented Feb 3, 2021

Tests were not as bad as they initially seemed, fixed now.

My primary concerns for adding this feature are that

  • users will be annoyed by Scrollbars showing up where they are not wanted
  • users that are already using Scrollbars on desktop/web will be broken by duped Scrollbars
  • users implementing or extending buildViewportChrome will be broken
  • creating scrollbars on mobile will require the user to add special handling when their app in on web/desktop, lest be affected by the duped scrollbar exception mentioned above
    • or they could turn off autoScrollbars all together and have no issue - which I think kind of nullifies the point of this feature.

@flutter-dashboard flutter-dashboard bot added f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. labels Feb 3, 2021
@kunit1
Copy link

kunit1 commented Feb 4, 2021

From a framework user's perspective I think it's concerning that I have to worry about double scrollbars. If this feature is to be implemented I would assume that the framework will handle figuring out if I added a scrollbar explicitly or I am relying on automated scrollbar feature. If this detection is not possible then I would rather not have this feature. Just sharing my opinion, for what it's worth.

@Piinks
Copy link
Contributor Author

Piinks commented Feb 4, 2021

Thanks @kunit1, I agree. I'm gathering more feedback as well from the rest of the team.

I would assume that the framework will handle figuring out if I added a scrollbar explicitly or I am relying on automated scrollbar feature. If this detection is not possible then I would rather not have this feature.

I don't think we can automatically detect a Scrollbar. They can be placed anywhere in the tree, and even if we could track them all down, we would need to distinguish which were made automatically and which were user generated.
Also, there is already a pattern of use where the Scrollbar listens to more than one Scrollable. I've seen this most often with 2D scrolling.

In general, I try to avoid automatically making decisions for users like this.

@Piinks Piinks changed the title [WIP] Automatically applied Scrollbars on Desktop & Web Automatically applied Scrollbars on Desktop in ScrollBehaviors Mar 11, 2021
@Piinks Piinks marked this pull request as ready for review March 11, 2021 23:53
@Piinks
Copy link
Contributor Author

Piinks commented Mar 11, 2021

The preceding change has landed, this has been updated and is ready for review. :)

/// For example, based on the platform and provided details, this method
/// could wrap a given widget with a [GlowingOverscrollIndicator] to provide
/// visual feedback when the user overscrolls.
Widget buildViewportDecoration(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Hixie, you had asked about this signature in the design doc, I created ScrollableDetails as you suggested. I agree it will make this more future proof if we need more information later.

@Piinks Piinks requested a review from gspencergoog March 12, 2021 00:26
@goderbauer
Copy link
Member

Looks like the analyzer is not happy.

final AxisDirection direction;

/// A [ScrollController] that can be used to control the position of the
/// [Scrollable] widget.
Copy link
Member

Choose a reason for hiding this comment

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

Document what it means to set this to null or non-null?

Copy link
Member

Choose a reason for hiding this comment

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

Maybe we should even rename this to make it clear that this is the controller for the scrollbar?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am hesitant to name this as specific to scrollbars, the controller may be used in the future for other things.

@Piinks Piinks requested a review from goderbauer March 15, 2021 19:54
@Piinks Piinks removed f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. labels Mar 15, 2021
@Piinks Piinks requested a review from goderbauer March 17, 2021 22:23
Widget child,
ScrollableDetails details,
) {
// No GlowingOverscrollIndicator or Scrollbar applied.
Copy link
Member

Choose a reason for hiding this comment

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

Why no scrollbar? Don't they need one on desktop?

physics: widget.scrollPhysics,
dragStartBehavior: widget.dragStartBehavior,
restorationId: widget.restorationId,
autoScrollbar: false,
Copy link
Member

Choose a reason for hiding this comment

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

If this is a multiline textfield, doesn't it need scrollbars to scroll up and down?

Axis get axis => axisDirectionToAxis(axisDirection);

/// {@template flutter.widgets.scrollable.autoScrollbar}
/// Whether a [Scrollbar] should automatically be applied to this Scrollable.
Copy link
Member

Choose a reason for hiding this comment

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

This property only takes affect when a controller is also provided, though, right?

@goderbauer
Copy link
Member

I thought about this a little more: It seems like we have cases where we want a scrollbar, but not glow (DropDown menu?) and cases where we want a glow, but no scrollbar (PageView). Do we need to disentangle the glow and the scrollbar stuff?

Here's an idea I had: We could change the ScrollBehavior class to represent something like the following:

class ScrollBehavior {
  
  @protected
  Widget buildViewportChrome(BuildContext context, Widget child, AxisDirection axisDirection) {
    // current implementation, unchanged, mainly used for glow
  }

  @protected
  Widget buildScrollbars(BuildContext context, Widget child, ScrollableDetails details,) {
    // wraps child in scrollbars (or returns the child directly)
  }

  // Called by the Scrollable instead of buildViewportChrome.
  Widget buildViewportDecorations(BuildContext context, Widget child, ScrollableDetails details,) {
    return buildViewportChrome(context, buildScrollbars(context, child, details), details.axisDirection);
  }

  // probably needs a different name?
  ScrollBehavior copyWith({bool chrome = true, bool = scrollbars = true}) {
    return _WrappedScrollBehavior(this, chrome: chrome, scrollbars: scrollbars);
  }

  // Other stuff in ScrollBehavior

}

The _WrappedScrollBehavior basically forwards all calls to the wrapped instance, except if chrome or scrollbars is false it returns the child unwrapped from buildScrollbars or buildViewportDecorations, respectively.

Furthermore, we change Scrollable to take an optional ScrollBehavior (if it is not provided, it looks one up in the tree like it does today). (This is similar to how it already takes an optional physics param.)

Now widgets that don't want scrollbars can pass ScrollConfigoration.of(context).copyWith(scrollbars: false) to the scrollable as behavior. Similar for widgets that don't need a glow.

As a bonus: This shouldn't be breaking.

Last, but not least, we need to change Scrollable to always have a ScrollController (if none was passed in, it creates one locally) to always pass it to ScrollDetails for the ScrollBehavior (otherwise we wouldn't be able to build the scrollbar).

@Piinks
Copy link
Contributor Author

Piinks commented Mar 18, 2021

Hm, let me experiment and see what this would look like. My first impression is that it's a bit complicated, and possibly hard to understand why buildViewportChrome is just for the glow while there are other methods for other decorations.
Also, how does this look if in the future we add more decorations?

I'll play with this a bit more..

@Piinks
Copy link
Contributor Author

Piinks commented Mar 20, 2021

Closing in favor of #78588

@Piinks Piinks closed this Mar 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: desktop Running on desktop c: API break Backwards-incompatible API changes c: new feature Nothing broken; request for a new capability customer: crowd Affects or could affect many people, though not necessarily a specific customer. f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. platform-web Web applications specifically

Projects

None yet

Development

Successfully merging this pull request may close these issues.

☂️ Scrollbar Fixes & Updates Scrollbars should be always visible and instantiated by default on web and desktop

3 participants