Get Progress of Uinavigationcontroller Swipe Back

Get progress of UINavigationController swipe back

This is what seems to work:

    private var currentTransitionCoordinator: UIViewControllerTransitionCoordinator?

@objc private func onGesture(sender: UIGestureRecognizer) {
switch sender.state {
case .began, .changed:
if let ct = navigationController?.transitionCoordinator {
currentTransitionCoordinator = ct
}
case .cancelled, .ended:
currentTransitionCoordinator = nil
case .possible, .failed:
break
}

if let currentTransitionCoordinator = currentTransitionCoordinator {
print(currentTransitionCoordinator.percentComplete)
}

}

After you let go there is no way to get progress though. I tried preserving the coordinator for a bit longer and printing values on timer but I get a crash even.

Anyway, I assume this is what you need.

TEST SCENARIO:

Create a new project and navigate to main storyboard. Add a navigation controller and set its root view controller to ViewController in storyboard (remove the autogenerated root).

Then go to ViewController.swift and overwrite it with following:

import UIKit

class ViewController: UIViewController {

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

if let controller = navigationController, controller.viewControllers.count <= 1 { // Present it first time only
view.backgroundColor = UIColor.green
let newController = ViewController()
newController.view.backgroundColor = UIColor.red
navigationController?.interactivePopGestureRecognizer?.addTarget(newController, action: #selector(onGesture))
navigationController?.pushViewController(newController, animated: true)
}
}

private var currentTransitionCoordinator: UIViewControllerTransitionCoordinator?

@objc private func onGesture(sender: UIGestureRecognizer) {
switch sender.state {
case .began, .changed:
if let ct = navigationController?.transitionCoordinator {
currentTransitionCoordinator = ct
}
case .cancelled, .ended:
currentTransitionCoordinator = nil
case .possible, .failed:
break
}

if let currentTransitionCoordinator = currentTransitionCoordinator {
print(currentTransitionCoordinator.percentComplete)
}

}

}

You should be able to see percentage printed out as you drag your finger, dismissing currently pushed view controller.

How to enable back/left swipe gesture in UINavigationController after setting leftBarButtonItem?

First set delegate in viewDidLoad:

self.navigationController.interactivePopGestureRecognizer.delegate = self;

And then disable gesture when pushing:

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
[super pushViewController:viewController animated:animated];
self.interactivePopGestureRecognizer.enabled = NO;
}

And enable in viewDidDisappear:

self.navigationController.interactivePopGestureRecognizer.enabled = YES;

Also, add UINavigationControllerDelegate to your view controller.

Overriding back swipe gesture in UINavigationController

You can do this in a combination of the following:

Add a swipe gesture recognizer to your view controller:

Sample Image

Add the following to your view controller class:

import UIKit

class SwipeBackViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()

navigationController?.interactivePopGestureRecognizer?.isEnabled = false
}

@IBAction func swipeback(_ sender: UISwipeGestureRecognizer) {
navigationController?.popToRootViewController(animated: true)
}
}
  • The command in viewDidLoad disables the default swipe recogninzer in iOS
  • Then, the action associated with the swipe recognizer you added above handles the pop for you

My answer here goes into disabling the recognizer in more detail in case you have any questions on that.

iOS 7 uinavigationcontroller how to detect swipe?

The interactive pop gesture recognizer is exposed through UINavigationController's interactivePopGestureRecognizer property. You can add your own controller as a target of the gesture recognizer and respond appropriately:

@implementation MyViewController

...

- (void)viewDidLoad
{
[super viewDidLoad];

[self.navigationController.interactivePopGestureRecognizer addTarget:self
action:@selector(handlePopGesture:)];
}

- (void)handlePopGesture:(UIGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateBegan)
{
// respond to beginning of pop gesture
}
// handle other gesture states, if desired
}

...

@end

How to disable back swipe gesture in UINavigationController on iOS 7

I found a solution:

Objective-C:

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}

Swift 3+:
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false

Swipe to go back only works on edge of screen?

Apple says here :

interactivePopGestureRecognizer

The gesture recognizer responsible for popping the top view controller
off the navigation stack. (read-only)

@property(nonatomic, readonly) UIGestureRecognizer
*interactivePopGestureRecognizer

The navigation controller installs this gesture recognizer on its view
and uses it to pop the topmost view controller off the navigation
stack. You can use this property to retrieve the gesture recognizer
and tie it to the behavior of other gesture recognizers in your user
interface. When tying your gesture recognizers together, make sure
they recognize their gestures simultaneously to ensure that your
gesture recognizers are given a chance to handle the event.

So SloppySwiper library customise the UIPanGestureRecognizer.

Check out the library SloppySwiper, which achieves this by using UIPanGestureRecognizer and by recreating the default animation.

SloppySwiper:- UINavigationController delegate that allows swipe back gesture to be started from anywhere on the screen like instagram.

Usage of this library can be found here.

Cocoapods:- pod "SloppySwiper"

I test this library on ios7 and above. It works like a charm.

Changing back button in iOS 7 disables swipe to navigate back

IMPORTANT:
This is a hack. I would recommend taking a look at this answer.

Calling the following line after assigning the leftBarButtonItem worked for me:

self.navigationController.interactivePopGestureRecognizer.delegate = self;

Edit:
This does not work if called in init methods. It should be called in viewDidLoad or similar methods.



Related Topics



Leave a reply



Submit