Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix scrollbar margins #107172

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

Merged
merged 7 commits into from
Jul 14, 2022
Merged

Fix scrollbar margins #107172

merged 7 commits into from
Jul 14, 2022

Conversation

Piinks
Copy link
Contributor

@Piinks Piinks commented Jul 6, 2022

Fixes #106918

This makes it such that the margins of the main and cross axes are treated the same way.
The track paints the full extent, while the margins are only applied to the thumb.

This is part of a yak shave in the scrollbar, as part of another proposal I found some bugs and code rot. I am fixing these all individually so that the proposal is not muddied with bugs fixes and new features mixed together.

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 signed the CLA.
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I updated tests to check the change I am making, or this PR is test-exempt.
  • All existing and new tests are passing.

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

@flutter-dashboard flutter-dashboard bot added f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. labels Jul 6, 2022
@Piinks Piinks requested review from xu-baolin, snat-s and DavBot02 July 6, 2022 17:13
@Piinks Piinks added the a: quality A truly polished experience label Jul 6, 2022
Copy link
Member

@xu-baolin xu-baolin left a comment

Choose a reason for hiding this comment

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

Should _trackExtent in the getTrackToScroll be replaced with traversable extent?

@Piinks
Copy link
Contributor Author

Piinks commented Jul 7, 2022

Should _trackExtent in the getTrackToScroll be replaced with traversable extent?

Yes!

Good catch. This is exactly the kind of thing I am trying to make more consistent to avoid future bugs in the larger clean up PR. I'll fix it here.

@@ -568,15 +568,15 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
1.0);

// Scrollbar thumb respects margin, track paints full length.
final double traversibleTrackExtent = _trackExtent - (2 * mainAxisMargin);
final double traversableTrackExtent = _trackExtent - (2 * mainAxisMargin);
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'll wrap this up in a getter in the larger refactor that will follow this.

@Piinks Piinks requested a review from xu-baolin July 7, 2022 19:33
@xu-baolin
Copy link
Member

xu-baolin commented Jul 8, 2022

There are also some edge cases to confirm:

  1. Is the margin area interactive?
  2. we should skip paint if traversableTrackExtent <= 0;

final double fractionVisible = clampDouble(
(_lastMetrics!.extentInside - _mainAxisPadding) /
(_totalContentExtent - _mainAxisPadding),
0.0,
1.0);

I don't quite understand why we need to subtract the value of padding here, what do you think?

We can not assume that the content view applies to the paddings.
Such as this demo,

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      scrollBehavior: MaterialScrollBehavior().copyWith(scrollbars: false),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: MediaQuery(
        data: MediaQuery.of(context).copyWith(
          padding: EdgeInsets.all(50),
        ),
        child: RawScrollbar(
          mainAxisMargin: 0,
          crossAxisMargin: 0,
          trackVisibility: true,
          thumbVisibility: true,
          thickness: 20,
          thumbColor: Colors.black,
          trackColor: Colors.yellowAccent,
          trackBorderColor: Colors.pink,
          child: Column(
            children: [
              Center(
                child: SizedBox(
                  height: 300,
                  child: CustomScrollView(
                    primary: true,
                    slivers: [
                      SliverList(
                        delegate: SliverChildBuilderDelegate(
                          (c, i) => Container(
                              height: 50,
                              child: Center(child: Text('Item $i'))),
                          childCount: 12,
                        ),
                      )
                    ],
                  ),
                ),
              ),
              Container(height: 20, color: Colors.green)
            ],
          ),
        ),
      ),
    );
  }
}

@@ -1342,15 +1352,20 @@ class RawScrollbar extends StatefulWidget {
/// {@macro flutter.widgets.Scrollbar.scrollbarOrientation}
final ScrollbarOrientation? scrollbarOrientation;

/// Distance from the scrollbar's start and end to the edge of the viewport
/// in logical pixels. It affects the amount of available paint area.
/// Distance from the scrollbar thumb's start or end to the nearest edge of
Copy link
Member

Choose a reason for hiding this comment

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

ScrollbarPainter.mainAxisMargin's docs can update too.

@Piinks
Copy link
Contributor Author

Piinks commented Jul 11, 2022

There are also some edge cases to confirm:

Thank you so much for identifying these! I am following up on them and will have something back tomorrow. 🙏

@Piinks
Copy link
Contributor Author

Piinks commented Jul 14, 2022

  1. Is the margin area interactive?

I think it makes sense for that margin area of the track to be interactive. The hit testing uses the rects created for the track and thumb. So if you tap on the margin that is contained within the track, I think it makes sense that the track would respond.

  1. we should skip paint if traversableTrackExtent <= 0;

Done

I don't quite understand why we need to subtract the value of padding here, what do you think?

I agree! This is something I have been wondering too, it's part of the larger clean up I have a WIP PR on. I just split up the changes so that 1) they are easier to review and 2) I would know I did not break anything with the larger refactor with the new tests.

For the sample app that you have above, it does look off, but in other cases, like when there is a notch or the status bar area, the padding needs to be respected - like in #106834
I might experiment with that in a separate change as well.

@Piinks Piinks requested a review from xu-baolin July 14, 2022 19:24
Copy link
Contributor

@pdblasi-google pdblasi-google left a comment

Choose a reason for hiding this comment

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

LGTM

@Piinks Piinks added the autosubmit Merge PR when tree becomes green via auto submit App label Jul 14, 2022
@xu-baolin
Copy link
Member

I'm still a little worried about the impact of this change. First, there is a area where the thumb cannot reach in the main axle, which will mislead that the scrollable has not rolled to the edge of the view. Second, if we support buttons at both ends in the future, this margin area will be even more strange.

@Piinks Piinks removed the autosubmit Merge PR when tree becomes green via auto submit App label Jul 14, 2022
@auto-submit auto-submit bot merged commit 2987d9e into flutter:master Jul 14, 2022
@Piinks
Copy link
Contributor Author

Piinks commented Jul 14, 2022

First, there is an area where the thumb cannot reach in the main axle, which will mislead that the scrollable has not rolled to the edge of the view.

This is actually the default for the Cupertino scrollbar, it has default margins such that the scrollbar never reaches the end of the perceived track area.

Second, if we support buttons at both ends in the future, this margin area will be even more strange.

That is likely something we would address then, since this is currently hypothetical, we can't really account for it right now.

@Piinks
Copy link
Contributor Author

Piinks commented Jul 14, 2022

Agh the bot was too fast for me. @xu-baolin if you have string feelings about this and would like to discuss further, we can revert this.

@xu-baolin
Copy link
Member

This is actually the default for the Cupertino scrollbar, it has default margins such that the scrollbar never reaches the end of the perceived track area.

The Cupertino scrollbar doesn't have track color, right?

@xu-baolin
Copy link
Member

Considering that we have a 2D bar with track color, we need to configure margin in one corner to avoid crossover. It doesn't seem to be possible now, right?

@Piinks
Copy link
Contributor Author

Piinks commented Jul 14, 2022

The motivation for this change was the inconsistently in how margins were being handled. The cross axis margin applied to the thumb, and not the track, and so it seemed logical for the margin in the main axis to reflect the same behavior.

Would the padding sample you demonstrated above better handle the 2D case you mention? I don't know that the main axis margin makes sense from an api standpoint to pad the scrollbar.

Perhaps padding should be exposed on the scrollbar instead of only using the MediaQueryData above it. It would give the user more control in a way that makes sense. We can certainly do that in a follow up change along with the clean up.

Also - we've been looking into and official 2D scrolling solution that would support 2D scrollbars. It's not quite ready yet, but I am optimistic that in this case it will just work, and not require extra configuring by the user.

@xu-baolin
Copy link
Member

Perhaps padding should be exposed on the scrollbar instead of only using the MediaQueryData above it.

Totally agree.

@xu-baolin
Copy link
Member

LGTM

engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Jul 15, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 15, 2022
@Piinks Piinks mentioned this pull request Jul 15, 2022
8 tasks
camsim99 pushed a commit to camsim99/flutter that referenced this pull request Aug 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a: quality A truly polished experience f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Scrollbar margins are handled inconsistently
3 participants