Program Tip

leftBarButtonItem을 설정 한 후 UINavigationController에서 뒤로 / 왼쪽 스 와이프 제스처를 활성화하는 방법은 무엇입니까?

programtip 2020. 12. 9. 21:37
반응형

leftBarButtonItem을 설정 한 후 UINavigationController에서 뒤로 / 왼쪽 스 와이프 제스처를 활성화하는 방법은 무엇입니까?


나는 여기 에서 반대 문제를 얻었다 . 기본적으로 스택 iOS7의 뒤로 스 와이프 제스처가 UINavigationController표시 될 수 ViewController있습니다. 이제 self.navigationItem.leftBarButtonItem모든 ViewControllers.

다음은 코드입니다.

self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:LOADIMAGE(@"back_button") style:UIBarButtonItemStylePlain target:self action:@selector(popCurrentViewController)];

그 후에 navigationController.interactivePopGestureRecognizer는 비활성화됩니다. 사용자 지정을 제거하지 않고 팝 제스처를 활성화하려면 어떻게 leftBarButtonItem해야합니까?

감사!


viewDidLoad에서 첫 번째 대리자를 설정합니다.

self.navigationController.interactivePopGestureRecognizer.delegate = self;

그리고 푸시 할 때 제스처를 비활성화합니다.

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

그리고 viewDidDisappear에서 활성화하십시오.

self.navigationController.interactivePopGestureRecognizer.enabled = YES;

또한 UINavigationControllerDelegate뷰 컨트롤러에 추가 하십시오.


다음 두 가지 시나리오를 처리해야합니다.

  1. 스택에 새 뷰를 푸시 할 때
  2. 루트 뷰 컨트롤러를 표시 할 때

사용할 수있는 기본 클래스가 필요한 경우 Swift 3 버전이 있습니다.

import UIKit

final class SwipeNavigationController: UINavigationController {

    // MARK: - Lifecycle

    override init(rootViewController: UIViewController) {
        super.init(rootViewController: rootViewController)
    }

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)

        delegate = self
    }

    required init?(coder aDecoder: NSCoder) { 
        super.init(coder: aDecoder) 

        delegate = self 
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // This needs to be in here, not in init
        interactivePopGestureRecognizer?.delegate = self
    }

    deinit {
        delegate = nil
        interactivePopGestureRecognizer?.delegate = nil
    }

    // MARK: - Overrides

    override func pushViewController(_ viewController: UIViewController, animated: Bool) {
        duringPushAnimation = true

        super.pushViewController(viewController, animated: animated)
    }

    // MARK: - Private Properties

    fileprivate var duringPushAnimation = false

}

// MARK: - UINavigationControllerDelegate

extension SwipeNavigationController: UINavigationControllerDelegate {

    func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
        guard let swipeNavigationController = navigationController as? SwipeNavigationController else { return }

        swipeNavigationController.duringPushAnimation = false
    }

}

// MARK: - UIGestureRecognizerDelegate

extension SwipeNavigationController: UIGestureRecognizerDelegate {

    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        guard gestureRecognizer == interactivePopGestureRecognizer else {
            return true // default value
        }

        // Disable pop gesture in two situations:
        // 1) when the pop animation is in progress
        // 2) when user swipes quickly a couple of times and animations don't have time to be performed
        return viewControllers.count > 1 && duringPushAnimation == false
    }
}

UINavigationControllerDelegate다른 클래스에서 역할을해야하는 경우이 답변과 유사한 위임 전달자를 작성할 수 있습니다 .

Objective-C의 소스에서 수정 : https://github.com/fastred/AHKNavigationController


대리자를 설정할 때 효과적입니다.

self.navigationController.interactivePopGestureRecognizer.delegate = self;

다음 구현

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

그것은 나를 위해 작동합니다 Swift 3 :

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }

그리고 ViewDidLoad에서 :

    self.navigationController?.interactivePopGestureRecognizer?.delegate = self
    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true

iOS 10, Swift 3 에서 스 와이프하여 팝업보기 컨트롤러를 활성화 / 비활성화하는 가장 좋은 방법입니다 .

첫 화면의 경우 [스 와이프 제스처를 비활성화하려는 위치] :

class SignUpViewController : UIViewController,UIGestureRecognizerDelegate {

//MARK: - View initializers
override func viewDidLoad() {
    super.viewDidLoad()
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    swipeToPop()
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

func swipeToPop() {

    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true;
    self.navigationController?.interactivePopGestureRecognizer?.delegate = self;
}

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {

    if gestureRecognizer == self.navigationController?.interactivePopGestureRecognizer {
        return false
    }
    return true
} }

중간 화면의 경우 [스 와이프 제스처를 사용하려는 위치] :

class FriendListViewController : UIViewController {

//MARK: - View initializers
override func viewDidLoad() {

    super.viewDidLoad()
    swipeToPop()
}

func swipeToPop() {

    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true;
    self.navigationController?.interactivePopGestureRecognizer?.delegate = nil;
} }

스위프트 3 :

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

    self.navigationController?.interactivePopGestureRecognizer?.delegate = self
}

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return (otherGestureRecognizer is UIScreenEdgePanGestureRecognizer)
}

사용자 지정 뒤로 버튼을 설정하면 뒤로 스 와이프 기능이 비활성화됩니다.

The best thing to do to keep it is to subclass UINavigationViewController and set itself as the interactivePopGestureRecognizer delegate; then you can return YES from gestureRecognizerShouldBegin to allow the swipe back.

For example, this is done in AHKNavigationController

And a Swift version here: https://stackoverflow.com/a/43433530/308315


This answer, but with storyboard support.

class SwipeNavigationController: UINavigationController {

    // MARK: - Lifecycle

    override init(rootViewController: UIViewController) {
        super.init(rootViewController: rootViewController)
    }

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)

        self.setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        self.setup()
    }

    private func setup() {
        delegate = self
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // This needs to be in here, not in init
        interactivePopGestureRecognizer?.delegate = self
    }

    deinit {
        delegate = nil
        interactivePopGestureRecognizer?.delegate = nil
    }

    // MARK: - Overrides

    override func pushViewController(_ viewController: UIViewController, animated: Bool) {
        duringPushAnimation = true

        super.pushViewController(viewController, animated: animated)
    }

    // MARK: - Private Properties

    fileprivate var duringPushAnimation = false
}

For those who are still having trouble with this, try separating the two lines as below.

override func viewDidLoad() {
    self.navigationController!.interactivePopGestureRecognizer!.delegate = self
    ...

override func viewWillAppear(_ animated: Bool) {
    self.navigationController!.interactivePopGestureRecognizer!.isEnabled = true
    ...

Obviously, in my app,

interactivePopGestureRecognizer!.isEnabled

got reset to false before the view was shown for some reason.

참고URL : https://stackoverflow.com/questions/34942571/how-to-enable-back-left-swipe-gesture-in-uinavigationcontroller-after-setting-le

반응형