Blog coding and discussion of coding about JavaScript, PHP, CGI, general web building etc.

Saturday, July 23, 2016

No Swipe Back when hiding Navigation Bar in UINavigationController

No Swipe Back when hiding Navigation Bar in UINavigationController


I love the swipe pack thats inherited from embedding your views in a UINavigationController. Unfortunately i cannot seem to find a way to hide the navigation bar but still have the touch pan swipe back gesture. I can write custom gestures but I prefer not to and to rely on the UINavigationController back swipe gesture instead.

if I uncheck it in the storyboard, the back swipe doesn't work

enter image description here

alternatively if I programmatically hide it, the same scenario.

- (void)viewDidLoad  {      [super viewDidLoad];      [self.navigationController setNavigationBarHidden:YES animated:NO]; // and animated:YES  }  

Is there no way to hide the top Navigation bar and still have the swipe?

Answer by Mundi for No Swipe Back when hiding Navigation Bar in UINavigationController


Some people have had success by calling the setNavigationBarHidden method with animated YES instead.

Answer by HorseT for No Swipe Back when hiding Navigation Bar in UINavigationController


A hack that is working is to set the interactivePopGestureRecognizer's delegate of the UINavigationController to nil like this:

[self.navigationController.interactivePopGestureRecognizer setDelegate:nil];  

But in some situations it could create strange effects.

Answer by eddwinpaz for No Swipe Back when hiding Navigation Bar in UINavigationController


Here is how to disable de gesture recognizer when user slides out of the ViewController. You can paste it on your viewWillAppear() or on your ViewDidLoad() methods.

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

Answer by saranpol for No Swipe Back when hiding Navigation Bar in UINavigationController


In my case, to prevent strange effects

Root view controller

override func viewDidLoad() {      super.viewDidLoad()        // Enable swipe back when no navigation bar      navigationController?.interactivePopGestureRecognizer.delegate = self     }      func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {      if(navigationController!.viewControllers.count > 1){          return true      }      return false  }  

http://www.gampood.com/pop-viewcontroller-with-out-navigation-bar/

Answer by Yogesh Maheshwari for No Swipe Back when hiding Navigation Bar in UINavigationController


You can subclass UINavigationController as following:

@interface CustomNavigationController : UINavigationController    @end  

Implementation:

@implementation CustomNavigationController    - (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated {      [super setNavigationBarHidden:hidden animated:animated];      self.interactivePopGestureRecognizer.delegate = self;  }    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {      if (self.viewControllers.count > 1) {          return YES;      }      return NO;  }    @end  

Answer by Ahmad for No Swipe Back when hiding Navigation Bar in UINavigationController


Xamarin Answer:

Implement the IUIGestureRecognizerDelegate Interface in your ViewController's Class definition:

public partial class myViewController : UIViewController, IUIGestureRecognizerDelegate  

In your ViewController add the following method:

[Export("gestureRecognizerShouldBegin:")]  public bool ShouldBegin(UIGestureRecognizer recognizer) {    if (recognizer is UIScreenEdgePanGestureRecognizer &&         NavigationController.ViewControllers.Length == 1) {      return false;    }    return true;  }  

In your ViewController's ViewDidLoad() add the following line :

NavigationController.InteractivePopGestureRecognizer.Delegate = this;  

Answer by Nathan Perry for No Swipe Back when hiding Navigation Bar in UINavigationController


You can do it with a Proxy Delegate. When you are building the navigation controller, grab the existing delegate. And pass it into the proxy. Then pass all delegate methods to the existing delegate except gestureRecognizer:shouldReceiveTouch: using forwardingTargetForSelector:

Setup:

let vc = UIViewController(nibName: nil, bundle: nil)  let navVC = UINavigationController(rootViewController: vc)  let bridgingDelegate = ProxyDelegate()  bridgingDelegate.existingDelegate = navVC.interactivePopGestureRecognizer?.delegate  navVC.interactivePopGestureRecognizer?.delegate = bridgingDelegate  

Proxy Delegate:

class ProxyDelegate: NSObject, UIGestureRecognizerDelegate {      var existingDelegate: UIGestureRecognizerDelegate? = nil        override func forwardingTargetForSelector(aSelector: Selector) -> AnyObject? {          return existingDelegate      }        func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {          return true      }    }  

Answer by KarimIhab for No Swipe Back when hiding Navigation Bar in UINavigationController


I've tried this and it's working perfectly : How to hide Navigation Bar without losing slide-back ability

The idea is to implement "UIGestureRecognizerDelegate" in your .h and add this to your .m file.

- (void)viewWillAppear:(BOOL)animated {  // hide nav bar  [[self navigationController] setNavigationBarHidden:YES animated:YES];    // enable slide-back  if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {      self.navigationController.interactivePopGestureRecognizer.enabled = YES;      self.navigationController.interactivePopGestureRecognizer.delegate = self;    }  }    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {     return YES;    }  

Answer by Chris Vasselli for No Swipe Back when hiding Navigation Bar in UINavigationController


I found that other posted solutions overriding the delegate, or setting it to nil caused some unexpected behavior.

In my case, when I was on the top of the navigation stack and tried to use the gesture to pop one more, it would fail (as expected), but subsequent attempts to push onto the stack would start to cause weird graphical glitches in the navigation bar. This makes sense, because the delegate is being used to handle more than just whether or not to block the gesture from being recognized when the navigation bar is hidden, and all that other behavior was being thrown out.

From my testing, it appears that gestureRecognizer(_:, shouldReceiveTouch:) is the method that the original delegate is implementing to block the gesture from being recognized when the navigation bar is hidden, not gestureRecognizerShouldBegin(_:). Other solutions that implement gestureRecognizerShouldBegin(_:) in their delegate work because the lack of an implementation of gestureRecognizer(_:, shouldReceiveTouch:) will cause the default behavior of receiving all touches.

@Nathan Perry's solution gets close, but without an implementation of respondsToSelector(_:), the UIKit code that sends messages to the delegate will believe there is no implementation for any of the other delegate methods, and forwardingTargetForSelector(_:) will never get called.

So, we take control of `gestureRecognizer(_:, shouldReceiveTouch:) in the one specific scenario we want to modify the behavior, and otherwise forward everything else to the delegate.

import Foundation    class AlwaysPoppableNavigationController : UINavigationController {        private var alwaysPoppableDelegate: AlwaysPoppableDelegate!        override func viewDidLoad() {          super.viewDidLoad()            self.alwaysPoppableDelegate = AlwaysPoppableDelegate(navigationController: self, originalDelegate: self.interactivePopGestureRecognizer!.delegate!)          self.interactivePopGestureRecognizer!.delegate = self.alwaysPoppableDelegate      }  }    private class AlwaysPoppableDelegate : NSObject, UIGestureRecognizerDelegate {        var navigationController: AlwaysPoppableNavigationController      var originalDelegate: UIGestureRecognizerDelegate        init(navigationController: AlwaysPoppableNavigationController, originalDelegate: UIGestureRecognizerDelegate) {          self.navigationController = navigationController          self.originalDelegate = originalDelegate      }        @objc func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {          if self.navigationController.navigationBarHidden && navigationController.viewControllers.count > 1 {              return true          }          else {              return self.originalDelegate.gestureRecognizer!(gestureRecognizer, shouldReceiveTouch: touch)          }      }        override func respondsToSelector(aSelector: Selector) -> Bool {          if aSelector == #selector(gestureRecognizer(_:shouldReceiveTouch:)) {              return true          }          else {              return self.originalDelegate.respondsToSelector(aSelector)          }      }        override func forwardingTargetForSelector(aSelector: Selector) -> AnyObject? {          return self.originalDelegate      }  }  

Answer by Eneko Alonso for No Swipe Back when hiding Navigation Bar in UINavigationController


I have found that when using custom back buttons, the interactive pop gesture stops working (my take is that Apple cannot foresee how your custom back button will behave, so they disable the gesture).

To fix this, as other mentioned before, you can set the interactivePopGestureRecognizer.delegate property to nil.

In Swift, this can easily be done across your entire application by adding an extension for UINavigationController like this:

extension UINavigationController {        override public func viewDidLoad() {          super.viewDidLoad()          interactivePopGestureRecognizer?.delegate = nil      }    }  


Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72

0 comments:

Post a Comment

Popular Posts

Powered by Blogger.