Skip to content
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

Cupertino back gesture are disabled when using PageRouteBuilder #47441

Open
Elia-Darwish opened this issue Dec 19, 2019 · 7 comments
Open

Cupertino back gesture are disabled when using PageRouteBuilder #47441

Elia-Darwish opened this issue Dec 19, 2019 · 7 comments
Labels
c: new feature Nothing broken; request for a new capability f: cupertino flutter/packages/flutter/cupertino repository f: routes Navigator, Router, and related APIs. framework flutter/packages/flutter repository. See also f: labels. team-design Owned by Design Languages team triaged-design Triaged by Design Languages team

Comments

@Elia-Darwish
Copy link

Elia-Darwish commented Dec 19, 2019

Use case

I am using PageRouteBuilder to add fade transition to some of my routes.
I've noticed however that the swipe to go back on IOS is not working when doing so! Which is something I'm used to as an IOS user.
Which left me with either choosing a very pleasing to the eye page transitions or better user experience.

Proposal

I was thinking that exposing the private classes _CupertinoBackGestureDetector and _CupertinoBackGestureController which are used in the CupertinoPageRoute to achive the swipe to go back function, or improving the PageRouteBuilder to support that feature, will be a great thing to have!

@janmoppel janmoppel added f: routes Navigator, Router, and related APIs. framework flutter/packages/flutter repository. See also f: labels. c: new feature Nothing broken; request for a new capability labels Dec 19, 2019
@HansMuller HansMuller added the f: cupertino flutter/packages/flutter/cupertino repository label Dec 19, 2019
@kwent
Copy link

kwent commented Jan 22, 2020

Related to kalismeras61/flutter_page_transition#19

@nilsreichardt
Copy link
Contributor

This is so important! It's also the reason, why the animations package doesn't support iOS swipe back gesture :(

@tnaseem
Copy link

tnaseem commented Jun 16, 2020

Having the same issue, using the Animations package to do a fadethrough to the new route. Can't seem to swipe back on iOS!

  static Route fadeThrough(Widget widget, [Duration duration]) {
    return PageRouteBuilder(
      transitionDuration: duration ?? Duration(milliseconds: 750),
      pageBuilder: (context, animation, secondaryAnimation) => widget,
      transitionsBuilder: (context, animation, secondaryAnimation, child) {
        return FadeThroughTransition(animation: animation, secondaryAnimation: secondaryAnimation, child: child);
      },
    );
  }

I guess I'll have to stick to no page transitions for now, until a fix is found.

@djsjr
Copy link

djsjr commented May 2, 2021

Have you tried something like wrapping the page being pushed in a GestureDetector? It seems like it could be a makeshift solution. (I have implemented a way to change the direction of the transition but that can be ignored.)

SlideTransition(
            position: Tween<Offset>(
              begin: direction == Direction.slideDown
                  ? const Offset(0, -1)
                  : direction == Direction.slideUp
                      ? const Offset(0, 1)
                      : direction == Direction.slideLeft
                          ? const Offset(-1, 0)
                          : const Offset(1, 0),
              end: Offset.zero,
            ).animate(animation),
            child: GestureDetector(
              onHorizontalDragEnd: (dragEndDetails) {
                Navigator.pop(context);
              },
              child: page,
            ),
          ),

Unfortunately this pops from a swipe in either direction, but I'm sure a combination of one of GestureDetector callback options and properties of the details will make swipe direction detectable.

Also this swipedetector package might replace the GestureDetector, or I might even experiment with this swipe_back_detector specifically made for custom routes made with PageRouteBuilder (see example they give).

@r100-stack
Copy link

You can use a custom PageRouteBuilder and override buildTransitions().

For iOS, the default PageTransitionBuilder is CupertinoPageTransitionsBuilder(). So we can use that in buildTransitions(). This automatically give us the swipe right to go back gesture.

Here's some sample code for the CustomPageRouteBuilder:

class CustomPageRouteBuilder<T> extends PageRoute<T> {
  final RoutePageBuilder pageBuilder;
  final PageTransitionsBuilder matchingBuilder = const CupertinoPageTransitionsBuilder(); // Default iOS/macOS (to get the swipe right to go back gesture)
  // final PageTransitionsBuilder matchingBuilder = const FadeUpwardsPageTransitionsBuilder(); // Default Android/Linux/Windows

  CustomPageRouteBuilder({this.pageBuilder});

  @override
  Color get barrierColor => null;

  @override
  String get barrierLabel => null;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
    return pageBuilder(context, animation, secondaryAnimation);
  }

  @override
  bool get maintainState => true;

  @override
  Duration get transitionDuration => Duration(milliseconds: 900); // Can give custom Duration, unlike in MaterialPageRoute

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
    return matchingBuilder.buildTransitions<T>(this, context, animation, secondaryAnimation, child);
  }
}

Then to go to a new page:

GestureDetector(
  onTap: () => Navigator.push(
    context,
    CustomPageRouteBuilder(pageBuilder: (context, animation, secondaryAnimation) => NewScreen()),
  ),
  child: ...,
)

@y-alkhateeb
Copy link

y-alkhateeb commented Mar 13, 2022

Thanks, @rohan-kadkol, it's working with me after

 class AnimatedPage<T> extends PageRoute<T>{
  final RoutePageBuilder pageBuilder;
  final PageTransitionsBuilder matchingBuilder = const CupertinoPageTransitionsBuilder(); // Default iOS/macOS (to get the swipe right to go back gesture)
  // final PageTransitionsBuilder matchingBuilder = const FadeUpwardsPageTransitionsBuilder(); // Default Android/Linux/Windows

  AnimatedPage({
    RouteSettings? settings,
    required this.pageBuilder,
    this.transitionDuration = const Duration(milliseconds: 300),
    this.reverseTransitionDuration = const Duration(milliseconds: 300),
    bool fullscreenDialog = false,
  }) :
        super(settings: settings, fullscreenDialog: fullscreenDialog);

  @override
  final Duration reverseTransitionDuration;

  @override
  Color? get barrierColor => null;

  @override
  bool get opaque => true;

  @override
  bool get barrierDismissible => false;

  @override
  String? get barrierLabel => null;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
    return pageBuilder(context, animation, secondaryAnimation);
  }

  @override
  bool get maintainState => true;

  @override
  final Duration transitionDuration;

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
    return matchingBuilder.buildTransitions<T>(this, context, animation, secondaryAnimation, child);
  }

}

@ranaahmmi
Copy link

ranaahmmi commented Jun 7, 2022

We Can use CustomPageRouteBuilder to Achieve this

class CustomPageRouteBuilder<T> extends PageRoute<T> {
  CustomPageRouteBuilder({
    RouteSettings? settings,
    required this.pageBuilder,
    this.transitionsBuilder = _defaultTransitionsBuilder,
    this.transitionDuration = const Duration(milliseconds: 300),
    this.reverseTransitionDuration = const Duration(milliseconds: 300),
    this.opaque = true,
    this.barrierDismissible = false,
    this.barrierColor,
    this.barrierLabel,
    this.maintainState = true,
    bool fullscreenDialog = false,
  }) : super(settings: settings, fullscreenDialog: fullscreenDialog);

  final PageTransitionsBuilder matchingBuilder =
      const CupertinoPageTransitionsBuilder(); // Default iOS/macOS (to get the swipe right to go back gesture)

  final RoutePageBuilder pageBuilder;
  final RouteTransitionsBuilder transitionsBuilder;

  @override
  final Duration transitionDuration;

  @override
  final Duration reverseTransitionDuration;

  @override
  final bool opaque;

  @override
  final bool barrierDismissible;

  @override
  final Color? barrierColor;

  @override
  final String? barrierLabel;

  @override
  final bool maintainState;

  @override
  Widget buildPage(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
  ) {
    return pageBuilder(context, animation, secondaryAnimation);
  }

  @override
  Widget buildTransitions(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
    Widget child,
  ) {
    return matchingBuilder.buildTransitions<T>(
      this,
      context,
      animation,
      secondaryAnimation,
      child,
    );
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: new feature Nothing broken; request for a new capability f: cupertino flutter/packages/flutter/cupertino repository f: routes Navigator, Router, and related APIs. framework flutter/packages/flutter repository. See also f: labels. team-design Owned by Design Languages team triaged-design Triaged by Design Languages team
Projects
Development

No branches or pull requests