flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
166.46k stars 27.59k forks source link

Return a value from a route even if back gestures are used #152949

Open TomBursch opened 3 months ago

TomBursch commented 3 months ago

Use case

I want to be able to return a result from a page even when gestures are used (on IOS). Using PopScope is not viable since this disables gestures on iOS (https://github.com/flutter/flutter/issues/138624). The documentation https://docs.flutter.dev/cookbook/navigation/returning-data provides no information regarding gestures. Maybe I'm missing an obvious alternative solution?

My use case is:

The problem is that it is not possible to keep gestures enabled on the item view page, since I want to pop with data (changed or not).

Proposal

I've already suggested https://github.com/flutter/flutter/issues/118102 as a solution to this, but understandably, it's not a great API. As suggested in that issue, this issue is a more general description of the feature I want. Nonetheless, here is another possible solution 😄 Either something similar to PopScope that allows to edit the popped result could be added. For example:

PopResultOverride(
  onPop: (oldResult) {
    return newResult;
  },
  child: ...
)

Or allow iOS back gestures with pop scope but don't complete them when canPop=false and call onPopInvokedWithResult.

goderbauer commented 3 months ago

You could write a custom route that sets Route.currentResult: https://main-api.flutter.dev/flutter/widgets/Route/currentResult.html

TomBursch commented 3 months ago

Thanks for the response! Yeah, I'm aware of that, that's why I suggested https://github.com/flutter/flutter/issues/118102. The problem I have with this, is that it would lead to a lot of overwritten classes. Not only, all the possible Routes I use. But also widgets like the OpenContainer from the animations packages, which cannot use custom routes. On android, I use these instead of the navigator. This means in my code base, I can either completely overwrite the OpenContainer to use a custom route. Or, on my pages, I would need to check if I'm using my custom route that allows setting currentResult (i.e. platforms where I don't use the OpenContainer) and if the route doesn't, I need to add the PopScope and overwrite the result there like I do now.

I think there should be a simpler solution to it. I mean, it would already be enough to just overwrite the result from within onPopInvokedWithResult in PopScope. For example, by letting us return the new result value.

PopScope(
  canPop: true,
  onPopInvokedWithResult: (context, result) => newResult;
  ...
)

I know this would be a breaking change, that's why didn't initially suggest it. But it would be the cleanest solution IMO. With canPop: true iOS would still allow back gestures.