Skip to content

iOS 13 scrollbar #35829

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 36 commits into from
Jul 31, 2019
Merged

iOS 13 scrollbar #35829

merged 36 commits into from
Jul 31, 2019

Conversation

justinmc
Copy link
Contributor

@justinmc justinmc commented Jul 9, 2019

Description

This PR implements iOS 13's draggable scrollbar. It can be activated by long pressing on the scrollbar or dragging in from the right on top of the scrollbar.

long press drag from right

Related Issues

Closes #35127

Tests

I test dragging the scrollbar with long press and drag from right in packages/flutter/test/cupertino/scrollbar_test.dart.

Usage

I struggled to come up with a nice way for developers to use this feature, because by default, Flutter has no scrollbars. You must wrap your scrollable widget in a Scrollbar or CupertinoScrollbar to get one, but then these scrollbar widgets have no command over the scroll position.

The solution I ended up using requires a ScrollController to be passed in, like this:

PrimaryScrollController(
  controller: scrollController,
  child: CupertinoScrollbar(
    controller: scrollController,
    child: MyLongListView(),
  ),
),

@justinmc justinmc added framework flutter/packages/flutter repository. See also f: labels. f: cupertino flutter/packages/flutter/cupertino repository work in progress; do not review labels Jul 9, 2019
@justinmc justinmc self-assigned this Jul 9, 2019
@justinmc justinmc changed the title WIP iOS 13 scrollbar iOS 13 scrollbar Jul 19, 2019
@justinmc justinmc merged commit fb2f3e5 into flutter:master Jul 31, 2019
@justinmc justinmc deleted the ios13-scrollbar branch July 31, 2019 22:53
@Kavantix
Copy link
Contributor

Kavantix commented Aug 8, 2019

@justinmc I was just playing around with the scrollbar and comparing it to the native one.
What I noticed was firstly that the drag from the right was not something I can reproduce on a native app.
And also that the long press delay on a native app is almost instant, I would say around 150ms whereas on flutter right now it is half a second.

I managed to get the feel very close by removing the drag from the right gesture and adding a deadline field to the constructor of LongPressGestureRecognizer which I set to 150ms for the drag gesture.

@justinmc
Copy link
Contributor Author

justinmc commented Aug 8, 2019

@Kavantix I'm able to get the drag-from-right thing in the iOS 13 simulator, but it seems a little harder to activate than it is in Flutter now. I don't have an iOS 13 device at the moment to try it on. Maybe we could make it more strict. There are a few words mentioned about it in a Reddit thread.

You seem to be right that the long press threshold is shorter. Something like a deadline parameter might be a good way to solve that.

Would you mind opening an issue for these two points? That way anyone else having this problem can find your workaround and add to the discussion.

@Kavantix
Copy link
Contributor

Kavantix commented Aug 8, 2019

@justinmc see #37892

@justinmc
Copy link
Contributor Author

justinmc commented Aug 8, 2019

Thanks I appreciate it!

@Chimba123
Copy link

Hello, guys just trying this draggable scrollbar implementation in my flutter 1.9 stable upgrade but the draggable scrollbar is not working. Could it be that it is not yet available on the stable channel?

@justinmc
Copy link
Contributor Author

@Chimba123 It looks like this should be in >1.8.4, so your version looks good. Did you enable the feature properly? See the code block in the description up top that shows you how to enable this. For now it's not automatic.

@Chimba123
Copy link

@justinmc I did exactly that but it cannot find the controller in the PrimaryScrollView wrapping
I have initialized like so "ScrollController scrollController;"

@justinmc
Copy link
Contributor Author

Try this gist containing a full demo app that I know should work: https://gist.github.com/justinmc/3c58cb125644b230fe66832b0ea541c2

@Chimba123
Copy link

@justinmc "final ScrollController scrollController = ScrollController();" was the key thanks it works appreciate it

@justinmc
Copy link
Contributor Author

No problem!

rcunning added a commit to rcunning/flutter-slide-container that referenced this pull request Sep 12, 2019
@Chimba123
Copy link

Then another issue, how do we use this functionality in a CustomScrollView Widget with a linear list of scrolling widgets?

@justinmc
Copy link
Contributor Author

@Chimba123
Copy link

Chimba123 commented Sep 16, 2019

@justinmc my problem is like this (snippet below)

 Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      child: CustomScrollView(
        slivers: <Widget>[
          SliverPersistentHeader(
            delegate: MyNav(),
            pinned: true,
            floating: false,
          ),
SliverList(),
        ],
      ),
    );
  }
}

I have a navbar if I use that method in the link the scrollbar scrolls above the navbar, I want it under

@Chimba123
Copy link

Chimba123 commented Sep 16, 2019

@justinmc I have found a way just wrap it in a SliverToBoxAdapter and set the media constraints of the containing widget like below

@override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      child: CustomScrollView(
        slivers: <Widget>[
          SliverPersistentHeader(
            delegate: MyNav(),
            pinned: true,
            floating: false,
          ),
          SliverToBoxAdapter(
           child: Container(
             height: MediaQuery.of(context).size.height,
              width:MediaQuery.of(context).size.width,
             child: PrimaryScrollController(
               controller: scrollController,
               child: CupertinoScrollbar(
                 controller: scrollController,
                 child: MediaQuery.removePadding(
                     context: context,
                     removeTop: true,
                     child: Container()
                   ),
               ),
             ),
           ),
           ),
        ],
      ),
    );
  }
}

@justinmc
Copy link
Contributor Author

Ok good to hear you got it, thanks for following up. I will edit your comments for formatting really quick.

@SixSheeppp
Copy link

@justinmc Hi. Could u add a property to set the Scrollbar show or hide. Or just like this typedef ScrollBarCanShow = bool Function(); let the user make Scrollbar show or hide according to logic.

@justinmc
Copy link
Contributor Author

Could you get the same outcome by removing the scrollbar from the widget tree? Like:

if (_showScrollbar) {
  return Scrollbar(
    child: MyListView(),
  );
}
return MyListView(); 

@SahajRana
Copy link
Contributor

Hi @justinmc, This PR has been really helpful. I tried it with two ScrollViews. One vertical, other Horizontal, like

PrimaryScrollController(
                 controller: scrollController,
                 child: CupertinoScrollbar(
                          controller: scrollController,
                          child: SingleChildScrollView(
                                    scrollDirection: Axis.vertical,
                                    child: SingleChildScrollView(
                                        scrollDirection: Axis.horizontal,

So, Vertical scroll drag works well. But, when I tried horizontal, it automatically switches to the vertical scroll. Is there a way to solve this? (I have tried it on windows app).

@justinmc
Copy link
Contributor Author

@SahajRana Does it work without the CupertinoScrollbar? I believe you can't get bidirectional scrolling to work with this approach. If you can post a full minimal app that reproduces the problem I can take a closer look.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
f: cupertino flutter/packages/flutter/cupertino repository framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[iOS 13] Draggable Scrollbar
8 participants