Show RefreshIndicator on top when scroll's axis direction is up (matching native behaviour)#93779
Conversation
reverse property to `RefreshIndicatorreverse property to RefreshIndicator
|
I want this one!! |
darrenaustin
left a comment
There was a problem hiding this comment.
Thanks for the contribution. Looks good. Just a small typo and a question below.
It is a shame we can't have some way for this to just track the reverse setting on the scrollable descendent so that this just works out of the box, but this at least gives apps the ability to manually set both the scrollable and the indicator to handle the reverse case.
Piinks
left a comment
There was a problem hiding this comment.
It is a shame we can't have some way for this to just track the reverse setting on the scrollable descendent so that this just works out of the box
You should be able to do this by checking the AxisDirection of the notification. That is how we do this in widgets like the Scrollbar.
It looks like the RefreshIndicator already does this though. When the ListView is reversed, the RefreshIndicator moves to the bottom, so it is always there at the leading edge of the scroll view. I think what this is trying to do is put it at the trailing edge instead.
Yeah, it does track the scroll direction properly. The request from #26758 was to have it appear at the top of the list if the ListView is using the Which now that I think about it, the request seems a bit odd. The whole UI gesture of 'pull down to refresh' is built on the idea that new items usually appear at the top of the list, so you scroll to the top of the list and 'pull' for more. In the case of a chat app using the reverse setting, new items will appear at the bottom, so pulling down from the top is a little odd. |
341ea4d to
86cea90
Compare
86cea90 to
c421f20
Compare
reverse property to RefreshIndicatorRefreshIndicator on top when scroll's axis direction is up (matching native behavioiur)
|
@darrenaustin @Piinks |
RefreshIndicator on top when scroll's axis direction is up (matching native behavioiur)RefreshIndicator on top when scroll's axis direction is up (matching native behaviour)
Piinks
left a comment
There was a problem hiding this comment.
This is great - thank you for pursuing a full fidelity update here.
I have added @nt4f04uNd because they are working on a big fidelity update as well, review not necessary, just added as an FYI :)
| ); | ||
|
|
||
| await tester.fling(find.text('X'), const Offset(0.0, -300.0), 1000.0); | ||
| await tester.fling(find.text('X'), const Offset(0.0, 600.0), 1000.0); |
There was a problem hiding this comment.
I'm running this PR through internal testing now, I am concerned it may be breaking, but hopeful it won't be.
There was a problem hiding this comment.
@darrenaustin actually approved this (so I won't make changes to turn it into parameter based direction)
Can you please take a look if this breaks any internal tests?
There was a problem hiding this comment.
Out internal presubmit tester is having some issues, I think this is ok to land though.
nt4f04uNd
left a comment
There was a problem hiding this comment.
I feel like this is probably a case where we should provide a better behavior for users, rather than match the native behavior. It seems right to me that refresh indicator shows by default at the leading extent.
Although, #26758 seems a valid feature request and is saying they want to change this behavior, so perhaps the reverse (or something like appearAtEnd) parameter is a better way to go? Adding docs about all of this also would be good.
What do you guys think?
|
I also cloned your PR and tried running it with BouncingScrollPhysics, and refresh indicator didn't appear anywhere |
|
@nt4f04uNd |
|
@nt4f04uNd |
|
@nt4f04uNd @Piinks Minimal example, this never triggers overscroll. Also, the Troubleshooting section in the documentation also suggests this and stackoverflow |
|
I think @TahaTesser's comment about BouncingScrollPhysics not being compatible by default makes sense. The docs for BouncingScrollPhysics even mention there are caveats to this type of ScrollPhysics triggering overscroll:
And the docs for the refresh indicator specify you need to trigger an overscroll to trigger the refresh. We may be able to make this clearer though in the docs. Often on iOS you'll find that AlwaysScrollableScrollPhysics being used with BouncingScrollPhysics. :) |
Piinks
left a comment
There was a problem hiding this comment.
I am not sure this achieves the desired result after checking it out and testing.
If I use the following sample (from the api docs, master branch: https://master-api.flutter.dev/flutter/material/RefreshIndicator-class.html), on iOS it works fine, until I set reverse true on the ListView. Then I can't make the refresh indicator appear at all. It doesn't seem right that it works for reverse: false, but not reverse: true now.
On Android, it appears to work fine both ways.
This seems like it might be broken, can you take a look @TahaTesser?
Here's the code sample:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'RefreshIndicator Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: RefreshIndicatorExample(title: _title),
);
}
}
class RefreshIndicatorExample extends StatefulWidget {
const RefreshIndicatorExample({Key? key, required this.title})
: super(key: key);
final String title;
@override
State<RefreshIndicatorExample> createState() =>
_RefreshIndicatorExampleState();
}
class _RefreshIndicatorExampleState extends State<RefreshIndicatorExample> {
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
GlobalKey<RefreshIndicatorState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: RefreshIndicator(
key: _refreshIndicatorKey,
color: Colors.white,
backgroundColor: Colors.blue,
strokeWidth: 4.0,
onRefresh: () async {
// Replace this delay with the code to be executed during refresh
// and return a Future when code finishs execution.
return Future<void>.delayed(const Duration(seconds: 3));
},
// Pull from top to show refresh indicator.
child: ListView.builder(
reverse: true,
itemCount: 25,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text('Item $index'),
);
},
),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
// Show refresh indicator programmatically on button tap.
_refreshIndicatorKey.currentState?.show();
},
icon: const Icon(Icons.refresh),
label: const Text('Show Indicator'),
),
);
}
}c421f20 to
fed4f5a
Compare
|
Gold has detected about 38 new digest(s) on patchset 3. |
|
@Piinks Looks like I missed adjusting PreviewScreen.Recording.2022-02-17.at.11.41.44.movI've renamed some existing tests to match new behavior |
Piinks
left a comment
There was a problem hiding this comment.
LGTM! Thank you for the quick follow up!
fed4f5a to
facec0f
Compare
…s up (matching native behaviour) (flutter/flutter#93779)
…s up (matching native behaviour) (flutter/flutter#93779)
…s up (matching native behaviour) (flutter/flutter#93779)
…s up (matching native behaviour) (flutter/flutter#93779)
…s up (matching native behaviour) (flutter/flutter#93779)
…tching native behaviour) (flutter#93779)
|
Hey @TahaTesser , I tried this code with reverse set to true but it is not working for me. Can you please suggest what change I need to make environment: |
|
Hello @TahaTesser Do I understand correctly that RefreshIndicator is not supposed to work with reverse list view? Thanks |
I agree |
Fixes #26758
Created a repo for testing
RefreshIndicatorwithSwipeRefreshLayouthttps://github.com/TahaTesser/refresh_indicator_reverse_example
(Based on https://github.com/nt4f04uNd/tabs_overlay, thanks @nt4f04uNd)
Showcase
This is commonly used in a chat app where new messages appear on top in a reversed list and when user want to load previous messages they scroll from top and indicator is shown for loading older messages (as new messages always at the bottom and these messages are usually loaded first).
Also looks like
SwipeRefreshLayoutdoesn't support pull from bottom https://stackoverflow.com/questions/24867204/swiperefreshlayout-pull-from-bottomThis PR shows
RefreshIndicatoron top when scroll's axis direction is up (matching native behaviour)Current behaviour when
RefreshIndicatoris wrapped around reverse ListView.RefreshIndicatorwhile Android doesn't.SwipeRefreshLayouttriggered by Android.With this PR, when
RefreshIndicatoris wrapped around reverse ListViewRefreshIndicatormatching Android behaviourRefreshIndicator&SwipeRefreshLayoutare triggered.Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.