Skip to content

Added new RefreshIndicator widget to be used with SliverAppBar. - #105769

Closed
elbeicktalat wants to merge 10 commits into
flutter:masterfrom
elbeicktalat:fix_54272
Closed

elbeicktalat wants to merge 10 commits into
flutter:masterfrom
elbeicktalat:fix_54272

Conversation

@elbeicktalat

@elbeicktalat elbeicktalat commented Jun 10, 2022 •

Copy link
Copy Markdown
Contributor

This PR. introduce a new widget called SliverRefreshIndicator which is the material equivalent to CupertinoSliverRefreshControl, both widget are subclasses of BaseSliverRefreshControl which holds the shared logic.

It is also provide a new named constructor partiallyRevealed to the existing RefreshProgressIndicator, which allows the getting RefreshProgressIndicator based on passed progress value.

Fix #54272

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 added new tests to check the change I am making, or this PR is [test-exempt].
  • All existing and new tests are passing.

@flutter-dashboard flutter-dashboard Bot added d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos documentation p: cupertino_ui cupertino_ui package in flutter/packages p: material_ui material_ui package in flutter/packages f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. c: contributor-productivity Team-specific productivity, code health, technical debt. labels Jun 10, 2022
@Piinks
Piinks self-requested a review June 10, 2022 19:24
@Piinks

Piinks commented Jun 10, 2022

Copy link
Copy Markdown
Contributor

Self-pinging to put this in my inbox for review. Thank you for putting this together. It looks like the failing tests are either broken doc references, analyzer issues or an issue with the sample code you are adding.

It sounds like this PR is really two features as described above. Can this be split into two separate PRs then? It makes it easier to review, but more importantly, if 1 of 2 features causes an issue, it will be reverted, meaning both would have to be reverted rather than just the one.

@elbeicktalat

Copy link
Copy Markdown
Contributor Author

I think it doesn't make sense splitting this in two PR. since they are related to each other.

In the end, if you see that essential splitting this in two PR. then I'll do it.

Thank you!

@Piinks Piinks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can you see about resolving the failures below first? Then we can give this a proper review.
Also, the sample code you have written requires tests to ensure it works as expected. Those tests can be found under examples/api/test.
Thanks!

Comment on lines +1570 to +1571
childCount: 20,
(BuildContext context, int index) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is causing one of the analysis failures the named parameter should come after the builder.

Comment on lines +23 to +24
childCount: testListLength,
(BuildContext context, int index) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same analysis error here

Comment on lines +634 to +639
/// When the user scrolls past [refreshTriggerPullDistance],
/// this sample shows material pull to refresh indicator for 1 second and
/// adds a new item to the top of the list view.
///
/// ** See code in examples/api/lib/material/refresh_indicator/sliver_refresh_control.0.dart **
/// {@end-tool}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is causing some of the failures as well. Can you check that the sample code follows the same pattern as other samples? It is throwing an error.

/// * [CustomScrollView], a typical sliver holding scroll view this control
/// should go into.
/// * [RefreshIndicator], a Material Design version of the pull-to-refresh
/// paradigm. This widget works differently than [SliverRefreshControl]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There does not appear to be a class with this name, this is one of the docs failures.

///
/// See also:
///
/// * [SliverRefreshControl], A sliver refresh control, that reflects the standard Material pull-to-refresh behavior.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same here, this does not exist.

// Flutter code sample for SliverRefreshIndicator

import 'package:flutter/material.dart';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The failing framework test shard is due to this sample code see logs below:

The following TestFailure was thrown running a test:
Expected: exactly one matching node in the widget tree
  Actual: _WidgetTypeFinder:<zero widgets with type "WidgetsApp" (ignoring offstage widgets)>
   Which: means none were found but one was expected
When the exception was thrown, this was the stack:
#4      main.<anonymous closure> (file:///tmp/flutter%20sdk/examples/api/integration_test/smoke_integration_test.dart:2457:9)
<asynchronous suspension>
<asynchronous suspension>
(elided one frame from package:stack_trace)
This was caught by the test expectation on the following line:
  file:///tmp/flutter%20sdk/examples/api/integration_test/smoke_integration_test.dart line 2457
The test description was:
  Smoke test material/refresh_indicator/sliver_refresh_indicator.0.dart

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would refer to other sample code to see if there is something missing from your case here.

@Piinks

Piinks commented Jun 13, 2022

Copy link
Copy Markdown
Contributor

I think it doesn't make sense splitting this in two PR. since they are related to each other.

One way to tell is, how does adding partiallyRevealed resolve #54272? If it does not resolve the issue, it should probably be a separate PR.

Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
physics: const BouncingScrollPhysics(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this required for this to work? This would not match native scroll physics for folks that want a native look and feel on Android.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, this is required to create a overscrolling space which is not available the the older versions of android, I don't think that flutter dose include the new behavior of native android.

Is this can be considered as an issue?

@Piinks

Piinks commented Jun 13, 2022

Copy link
Copy Markdown
Contributor

Also of note, the material version here does not currently match the native behavior.

This is the current behavior of RefreshIndicator:

Screen.Recording.2022-06-13.at.5.46.35.PM.mov

And this is the proposed sliver refresh here:

Screen.Recording.2022-06-13.at.5.43.41.PM.mov

The behavior does not look quite right. Can you take a look?

This page should detail of the expected behaviors of this widget:
https://material.io/design/platform-guidance/android-swipe-to-refresh.html#usage

const SliverRefreshIndicator({
super.key,
super.refreshTriggerPullDistance,
super.refreshIndicatorExtent,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The material refresh indicator does not occupy any layoutExtent or scrollExtent, see: https://material.io/design/platform-guidance/android-swipe-to-refresh.html#usage

/// A builder that's called as this sliver's size changes, and as the state
/// changes.
///
/// Can be set to null, in which case nothing will be drawn in the overscrolled

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This doesn't seem to be true. It falls back to buildRefreshIndicator in _BaseSliverRefreshControlState.build. Is there a reason you're making this change?

/// When provided, the value of [progress] must be between 0.0
/// and 1.0 (full circle) inclusive. Defaults to 1.0.
/// {@macro flutter.material.ProgressIndicator.ProgressIndicator}
const RefreshProgressIndicator.partiallyRevealed({

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The cupertino refresh control reveals the "spinner" slice by slice as you drag thus the name (see the gif here: https://stackoverflow.com/questions/29791995/swift-pull-to-refresh). The material circular progress indicator doesn't do the same so partiallyRevealed doesn't seem to accurately reflect the actual behavior.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Without partiallyRevealed the result will be like:

Screen_Recording_20220614-101128.mp4

As you scroll the RefreshIndicator is being animated.

With partiallyRevealed the result like:

Screen_Recording_20220614-101207.mp4

}

class _CircularProgressIndicatorState extends State<CircularProgressIndicator> with SingleTickerProviderStateMixin {
class _CircularProgressIndicatorState<T extends CircularProgressIndicator> extends State<T> with SingleTickerProviderStateMixin {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is there a reason this needs to be made a type parameter? RefreshProgressIndicator is already a subtype of CircularProgressIndicator.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well I have added a new property on the subclass without this I can't access to it. I could cast the super class as the subclass, but I think this is can be useful for the future.

return SizedBox(
width: radius * 2,
height: radius * 2,
child: FittedBox(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The material refresh indicator does not resize when you overscroll I think? If you use a FittedBox here it will expand when the user overscrolls and shrink when the scroll view bounces back.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This fit the circular indicator in the refresh indicator, other way the look will be like:

@elbeicktalat

Copy link
Copy Markdown
Contributor Author

Hi @Piinks,
I have fixed all errors, now the big deal is the behavior of the SliverRefreshIndicator, since this widget becomes part of the slivers, then I hit the following:

  1. The indicator can't begin behind of SliverAppBar.
  2. The CustomScrollView must have a physics of type BouncingScrollPhysics and it should be AlwaysScrollableScrollPhysics.

With the actual structure can arrive to something like:

Screen_Recording_20220614-145925.mp4

If this doesn't seems to be right, then probably I'll reset The CupertinoSliverRefreshControl and provide a dedicated implementation for SliverRefreshIndicatro.

Thank you!

@Piinks

Piinks commented Jun 21, 2022

Copy link
Copy Markdown
Contributor
  • The indicator can't begin behind of SliverAppBar.
  • The CustomScrollView must have a physics of type BouncingScrollPhysics and it should be AlwaysScrollableScrollPhysics.

This breaks the design of the Material indicator, so I do not think we will want to make this change. If there is a way to change this proposal and match the design spec, we can definitely take another look!

@elbeicktalat

elbeicktalat commented Jun 22, 2022 •

Copy link
Copy Markdown
Contributor Author

For sure I can get out of this issue, but I have to revert a few changes like: having a Base implementation for both iOS and Material.

Should I allow RefreshIndicator to warp the CustomListView, or make a new refresh indicator widget which becomes part of CustomListView?

Thanks!

@Piinks

Piinks commented Jun 22, 2022

Copy link
Copy Markdown
Contributor

Should I allow RefreshIndicator to warp the CustomListView, or make a new refresh indicator widget which becomes part of CustomListView?

Do you mean CustomScrollView? I am not sure! I would return to the issue you are trying to solve, and see what you think would be the best approach. I do have a proposal tat is almost finished that may resolve this, I would love your feedback on it when it is ready. :)

@Hixie

Hixie commented Sep 20, 2022

Copy link
Copy Markdown
Contributor

@elbeicktalat Will you be able to continue working on this? It's totally fine if not; we can take it over (though it might take longer). I'm just asking because I'm trying to clean out our review queue.

@elbeicktalat

Copy link
Copy Markdown
Contributor Author

Hi @Hixie I'm really sorry for the delay in responding,
I was working on this until @Piinks side to me that she has a solution for this, any way unfortunately I'm no more able to work on this, but I still able to give info if there is need.

Thanks, and again I'm sorry!

@Piinks

Piinks commented Dec 16, 2022

Copy link
Copy Markdown
Contributor

Hey @elbeicktalat, I am going to close this PR. I do still have plans to support this without breaking the current spec (#107182 was an earlier proposal), I just haven't circled back around to it yet.
I really appreciate your contribution and feedback on what we need to be supporting better here. Thank you!

@Piinks Piinks closed this Dec 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c: contributor-productivity Team-specific productivity, code health, technical debt. d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. p: cupertino_ui cupertino_ui package in flutter/packages p: material_ui material_ui package in flutter/packages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for RefreshIndicator to be used with SliverAppBar

4 participants