UINavigationController에서 탐색 모음을 숨길 때 뒤로 스 와이프하지 않음


86

.NET Framework에 뷰를 포함하여 상속 된 스 와이프 팩을 좋아합니다 UINavigationController. 불행히도 나는 숨길 방법을 찾지 못하는 것 NavigationBar같지만 여전히 터치 팬을 다시 스 와이프합니다 gesture. 사용자 지정 제스처를 작성할 수 있지만 UINavigationController뒤로 스 와이프를 gesture사용하지 않고 대신 사용하는 것을 선호 합니다.

스토리 보드에서 체크를 해제하면 뒤로 스 와이프가 작동하지 않습니다.

여기에 이미지 설명 입력

또는 프로그래밍 방식으로 숨기면 동일한 시나리오입니다.

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

상단을 숨기고 NavigationBar여전히 스 와이프 할 수있는 방법이 없습니까?


1
UIGestureRecognizer 추가가 허용됩니까? 쉽게 구현할 수 있습니다.
SwiftArchitect

1
@LancelotdelaMare, UINavigationController 백 스 와이프만큼 원활하게 작동하지 않기 때문에 피하려고했습니다. 일부 사람들이 도움이된다고 말했지만 아직 작동하지 않았기 때문에 UIScreenEdgePanGestureRecognizer를 조사하고 있습니다. 여기에서 가장 간단하고 우아한 솔루션을 찾으십시오.
미하이

답변:


96

작동하는 해킹은 interactivePopGestureRecognizer의 대리인을 다음 UINavigationControllernil같이 설정하는 것입니다.

[self.navigationController.interactivePopGestureRecognizer setDelegate:nil];

그러나 어떤 상황에서는 이상한 효과를 일으킬 수 있습니다.


16
"반복적으로 뒤로 스 와이프하면 스택에 뷰 컨트롤러가 하나만있을 때 제스처가 인식 될 수 있으며, 이로 인해 UI가 제스처 인식을 중지하는 (UIKit 엔지니어가 예상치 못한 것으로 생각합니다) 상태가됩니다."
HorseT

4
예상치 못한 상태로부터 보호 할 수있는 대안은이를 저수준 객체 (내 앱 델리게이트 사용)로 설정하고 구현 하여 의 개수가 0보다 크면 gestureRecognizerShouldBegin반환 true하는 것입니다.navigationControllerviewController
Kenny Winker

4
이것이 효과가 있지만 나는 이것에 대해 적극 권장합니다. 대리자를 중단하면 드물고 주 스레드 블록을 식별하기가 어렵습니다. 주 스레드 블록이 아니라 @HorseT가 설명한 내용이 밝혀졌습니다.
Josh Bernfeld

3
내 앱은 델리게이트 핸들을 저장 한 다음 복원 viewWillDisappear하고 지금까지 부작용이 발생하지 않았습니다.
Don Park

1
!!!! 반복 이상한 문제가 발생 강타를 사용할 때 높은이 솔루션을 사용 억제, 뒷면은 장애인 및 전체 응용 프로그램 넣은 사람은 아니다의 응답은 더 이상이다
KarimIhab

79

다른 방법의 문제

설정 interactivePopGestureRecognizer.delegate = nil에는 의도하지 않은 부작용이 있습니다.

설정 navigationController?.navigationBar.hidden = true은 작동하지만 탐색 모음의 변경 사항을 숨길 수는 없습니다.

마지막으로, 일반적으로 UIGestureRecognizerDelegate탐색 컨트롤러 용 모델 개체를 만드는 것이 좋습니다 . UINavigationController스택 의 컨트롤러로 설정 하면 EXC_BAD_ACCESS오류 가 발생합니다 .

전체 솔루션

먼저이 클래스를 프로젝트에 추가합니다.

class InteractivePopRecognizer: NSObject, UIGestureRecognizerDelegate {

    var navigationController: UINavigationController

    init(controller: UINavigationController) {
        self.navigationController = controller
    }

    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return navigationController.viewControllers.count > 1
    }

    // This is necessary because without it, subviews of your top controller can
    // cancel out your gesture recognizer on the edge.
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

그런 다음 탐색 컨트롤러 interactivePopGestureRecognizer.delegate를 새 InteractivePopRecognizer클래스 의 인스턴스로 설정합니다 .

var popRecognizer: InteractivePopRecognizer?

override func viewDidLoad() {
    super.viewDidLoad()
    setInteractiveRecognizer()
}

private func setInteractiveRecognizer() {
    guard let controller = navigationController else { return }
    popRecognizer = InteractivePopRecognizer(controller: controller)
    controller.interactivePopGestureRecognizer?.delegate = popRecognizer
}

상위 컨트롤러에 테이블, 컬렉션 또는 스크롤 뷰 하위보기가 있어도 작동하는 부작용없이 숨겨진 탐색 모음을 즐기십시오.


1
훌륭한 솔루션!
Matt Butler

1
최고의 답변, 감사합니다!
Dory Daniel

2
@HunterMaximillionMonk 훌륭한 솔루션에 감사드립니다. 그것은 매력처럼 작동합니다
diu

1
@HunterMaximillionMonk 이것은 올바르게 작동하는 것처럼 보이지만 여러 컨트롤러가 있으면 한 번 팝하면 작동이 중지됩니다.
Premal Khetani

1
확실히 최고의 답변입니다!
daxh

54

제 경우에는 이상한 효과를 방지하기 위해

루트 뷰 컨트롤러

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/


2
이 사용할 때 가끔 EXC_BAD_ACCESS 받고 있어요
안드레이 고르 디프

나를 위해, 그것은 제스처 일을하지 않고, 자주와 충돌EXEC_BAD_ACCESS
Benjohn

2
UIGestureRecognizerDelegate루트 뷰 컨트롤러 에 추가 하는 것을 잊지 gestureRecognizerShouldBegin마십시오. 제 경우에는 루트 뷰 컨트롤러보다 나중 뷰 컨트롤러에서 델리게이트가 nil로 설정되었으므로 루트 뷰 컨트롤러로 반환 될 때 호출되지 않았습니다. 그래서 배치 .delegate = selfviewDidAppear(). 제 경우에 이상한 효과가 해결되었습니다. 건배!
Wiingaard 2015

@AndreyGordeev 언제 EXEC_BAD_ACCESS발생하는지에 대해 자세히 설명해 주 시겠습니까?
Jaybo

여기에 대한 자세한 정보의 EXC_BAD_ACCESS오류 : stackoverflow.com/questions/28746123/...는
안드레이 고르 디프

25

iOS 13.4 용으로 업데이트 됨

iOS 13.4는 이전 솔루션을 깨뜨 렸으므로 상황이 추악해질 것입니다. iOS 13.4에서이 동작은 이제 private 메서드에 의해 제어되는 것처럼 보입니다 _gestureRecognizer:shouldReceiveEvent:( shouldReceiveiOS 13.4에 추가 된 새로운 공용 메서드 와 혼동하지 마십시오 ).


대리자를 재정의하거나 nil로 설정하는 다른 게시 된 솔루션이 예기치 않은 동작을 일으킨다는 것을 발견했습니다.

제 경우에는 탐색 스택의 맨 위에 있었고 제스처를 사용하여 하나를 더 팝하려고하면 실패 할 것입니다 (예상대로). 내비게이션 바. 이는 델리게이트가 내비게이션 바가 숨겨져있을 때 제스처가 인식되는 것을 차단할지 여부와 그 밖의 모든 동작이 삭제되는 것 이상을 처리하는 데 사용되기 때문에 의미가 있습니다.

내 테스트 gestureRecognizer(_:, shouldReceiveTouch:)에서 탐색 모음이 숨겨져있을 때 제스처가 인식되지 않도록 차단하기 위해 원래 대리자가 구현하는 방법 인 것으로 보입니다 gestureRecognizerShouldBegin(_:). gestureRecognizerShouldBegin(_:)델리게이트 작업 을 구현하는 다른 솔루션은 구현 이 없기 때문에 gestureRecognizer(_:, shouldReceiveTouch:)모든 터치를받는 기본 동작이 발생 하기 때문 입니다.

@Nathan Perry의 솔루션이 가까워 지지만를 구현하지 않으면 respondsToSelector(_:)델리게이트에 메시지를 보내는 UIKit 코드가 다른 델리게이트 메서드에 대한 구현이 없다고 믿고 forwardingTargetForSelector(_:)호출되지 않습니다.

따라서 동작을 수정하려는 특정 시나리오에서`gestureRecognizer (_ :, shouldReceiveTouch :)를 제어하고, 그렇지 않으면 나머지 모든 항목을 델리게이트에 전달합니다.

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 {

    weak var navigationController: AlwaysPoppableNavigationController?
    weak var originalDelegate: UIGestureRecognizerDelegate?

    init(navigationController: AlwaysPoppableNavigationController, originalDelegate: UIGestureRecognizerDelegate) {
        self.navigationController = navigationController
        self.originalDelegate = originalDelegate
    }

    // For handling iOS before 13.4
    @objc func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        if let navigationController = navigationController, navigationController.isNavigationBarHidden && navigationController.viewControllers.count > 1 {
            return true
        }
        else if let originalDelegate = originalDelegate {
            return originalDelegate.gestureRecognizer!(gestureRecognizer, shouldReceive: touch)
        }
        else {
            return false
        }
    }

    // For handling iOS 13.4+
    @objc func _gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceiveEvent event: UIEvent) -> Bool {
        if let navigationController = navigationController, navigationController.isNavigationBarHidden && navigationController.viewControllers.count > 1 {
            return true
        }
        else if let originalDelegate = originalDelegate {
            let selector = #selector(_gestureRecognizer(_:shouldReceiveEvent:))
            if originalDelegate.responds(to: selector) {
                let result = originalDelegate.perform(selector, with: gestureRecognizer, with: event)
                return result != nil
            }
        }

        return false
    }

    override func responds(to aSelector: Selector) -> Bool {
        if #available(iOS 13.4, *) {
            // iOS 13.4+ does not need to override responds(to:) behavior, it only uses forwardingTarget
            return originalDelegate?.responds(to: aSelector) ?? false
        }
        else {
            if aSelector == #selector(gestureRecognizer(_:shouldReceive:)) {
                return true
            }
            else {
                return originalDelegate?.responds(to: aSelector) ?? false
            }
        }
    }

    override func forwardingTarget(for aSelector: Selector) -> Any? {
        if #available(iOS 13.4, *), aSelector == #selector(_gestureRecognizer(_:shouldReceiveEvent:)) {
            return nil
        }
        else {
            return self.originalDelegate
        }
    }
}

1
귀하의 솔루션이이 순간에 가장 적합한 것 같습니다. 감사!
Timur Bernikovich

"하지만 스택으로 푸시하려는 후속 시도는 탐색 모음에서 이상한 그래픽 결함을 유발하기 시작합니다."-여기서 혼란 스럽습니다. 내비게이션 바가 없다고 생각 했나요? 그게 질문입니까? 내 상황에서는 내비게이션 컨트롤러가 navbar가없는 자식 뷰 컨트롤러로 내장되어 있습니다. 포함 된 VC에는 탐색 컨트롤이 있습니다. 그래서 나는 포함 된 VC를 인식기의 델리게이트가되게하고 그냥 그 gestureRecognizerShouldBegin:일을했습니다. 그리고 그것은 "작동하는 것 같습니다". 내가 찾아봐야 할까?
skagedal

2
navigationControllerAlwaysPoppableDelegate의 강력한 참조 이기 때문에 메모리 누수가 발생 했습니다. 이것을 weak참조 하기 위해 코드를 편집했습니다 .
Graham Perks

3
이 멋진 솔루션은 iOS 13.4에서 더 이상 작동하지 않습니다
Ely

@ChrisVasselli 정말 대단해, ​​감사합니다! 바라건대 이것은 App Store 검토의 비공개 메서드 검사를 통과 할 것입니다.
Ely

16

다음과 같이 UINavigationController를 하위 클래스로 만들 수 있습니다.

@interface CustomNavigationController : UINavigationController<UIGestureRecognizerDelegate>

@end

이행:

@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

2
이 접근 방식을 사용하면 UIPageViewController오버 스크롤 에서 팝 제스처가 깨 집니다.
atulkhatri

viewController.count> 1 확인이 필요하다는 것을 알았습니다. 사용자가 루트 VC 만 사용하여 뒤로 스 와이프하려고하면 UI가 다음 VC 푸시에서 중단됩니다.
VaporwareWolf

11

간단하고 부작용이없는 답변

여기에있는 대부분의 답변은 좋지만 의도하지 않은 부작용 (앱 중단)이 있거나 장황합니다.

제가 생각해 낼 수있는 가장 간단하면서도 기능적인 솔루션은 다음과 같습니다.

navigationBar를 숨기고있는 ViewController에서,

class MyNoNavBarViewController: UIViewController {
    
    // needed for reference when leaving this view controller
    var initialInteractivePopGestureRecognizerDelegate: UIGestureRecognizerDelegate?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // we will need a reference to the initial delegate so that when we push or pop.. 
        // ..this view controller we can appropriately assign back the original delegate
        initialInteractivePopGestureRecognizerDelegate = self.navigationController?.interactivePopGestureRecognizer?.delegate
    }

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

        // we must set the delegate to nil whether we are popping or pushing to..
        // ..this view controller, thus we set it in viewWillAppear()
        self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
    }

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

        // and every time we leave this view controller we must set the delegate back..
        // ..to what it was originally
        self.navigationController?.interactivePopGestureRecognizer?.delegate = initialInteractivePopGestureRecognizerDelegate
    }
}

다른 답변은 단순히 델리게이트를 nil로 설정하는 것을 제안했습니다. 탐색 스택에서 초기보기 컨트롤러로 뒤로 스 와이프하면 모든 제스처가 비활성화됩니다. 아마도 UIKit / UIGesture 개발자에 대한 일종의 감독입니다.

또한 여기에 구현 한 일부 답변은 비표준 애플 탐색 동작을 초래했습니다 (특히 뒤로 스 와이프하면서 위아래로 스크롤 할 수있는 기능을 허용 함). 이 답변은 또한 약간 장황하고 경우에 따라 불완전한 것처럼 보입니다.


viewDidLoad()거기에 없을 수 있기 initialInteractivePopGestureRecognizerDelegate때문에 캡처하기에 좋은 장소가 아닙니다 navigationController(아직 스택에 푸시되지 않음). viewWillAppear탐색 표시 줄을 숨기는 위치가 더 적절할 것입니다.
nCod3d

10

Hunter Maximillion Monk의 답변을 바탕 으로 UINavigationController에 대한 하위 클래스를 만든 다음 스토리 보드에서 UINavigationController에 대한 사용자 지정 클래스를 설정했습니다. 두 클래스의 최종 코드는 다음과 같습니다.

InteractivePopRecognizer :

class InteractivePopRecognizer: NSObject {

    // MARK: - Properties

    fileprivate weak var navigationController: UINavigationController?

    // MARK: - Init

    init(controller: UINavigationController) {
        self.navigationController = controller

        super.init()

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

extension InteractivePopRecognizer: UIGestureRecognizerDelegate {
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return (navigationController?.viewControllers.count ?? 0) > 1
    }

    // This is necessary because without it, subviews of your top controller can cancel out your gesture recognizer on the edge.
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

HiddenNavBarNavigationController :

class HiddenNavBarNavigationController: UINavigationController {

    // MARK: - Properties

    private var popRecognizer: InteractivePopRecognizer?

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
        setupPopRecognizer()
    }

    // MARK: - Setup

    private func setupPopRecognizer() {
        popRecognizer = InteractivePopRecognizer(controller: self)
    }
}

스토리 보드 :

스토리 보드 탐색 컨트롤러 사용자 정의 클래스


8

@ChrisVasseli에서 제공하는 솔루션이 최고인 것 같습니다. 질문은 Objective-C에 관한 것이므로 Objective-C에서 동일한 솔루션을 제공하고 싶습니다 (태그 참조)

@interface InteractivePopGestureDelegate : NSObject <UIGestureRecognizerDelegate>

@property (nonatomic, weak) UINavigationController *navigationController;
@property (nonatomic, weak) id<UIGestureRecognizerDelegate> originalDelegate;

@end

@implementation InteractivePopGestureDelegate

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if (self.navigationController.navigationBarHidden && self.navigationController.viewControllers.count > 1) {
        return YES;
    } else {
        return [self.originalDelegate gestureRecognizer:gestureRecognizer shouldReceiveTouch:touch];
    }
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
    if (aSelector == @selector(gestureRecognizer:shouldReceiveTouch:)) {
        return YES;
    } else {
        return [self.originalDelegate respondsToSelector:aSelector];
    }
}

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return self.originalDelegate;
}

@end

@interface NavigationController ()

@property (nonatomic) InteractivePopGestureDelegate *interactivePopGestureDelegate;

@end

@implementation NavigationController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.interactivePopGestureDelegate = [InteractivePopGestureDelegate new];
    self.interactivePopGestureDelegate.navigationController = self;
    self.interactivePopGestureDelegate.originalDelegate = self.interactivePopGestureRecognizer.delegate;
    self.interactivePopGestureRecognizer.delegate = self.interactivePopGestureDelegate;
}

@end

3
ObjC는 아직 죽지 않았기 때문입니다! 😉
MonsieurDart

2
이것이 올바른 해결책입니다. 원래 대리자에게 전달되지 않는 다른 솔루션은 올바르지 않습니다.
Josh Bernfeld 2017 년

6

내 해결책은 UINavigationController클래스 를 직접 확장하는 것 입니다.

import UIKit

extension UINavigationController: UIGestureRecognizerDelegate {

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

        self.interactivePopGestureRecognizer?.delegate = self
    }

    public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return self.viewControllers.count > 1
    }

}

이렇게하면 모든 내비게이션 컨트롤러가 슬라이딩으로 해제됩니다.


이상하게도 이로 인해 viewDidAppear탐색 컨트롤러에 속한 VC의 모든 호출이 무시됩니다.
cumanzor

4

프록시 대리인과 함께 할 수 있습니다. 탐색 컨트롤러를 만들 때 기존 대리자를 잡습니다. 그리고 그것을 프록시에 전달하십시오. 그런 다음 gestureRecognizer:shouldReceiveTouch:사용 하는 것을 제외하고 모든 델리게이트 메서드를 기존 델리게이트에 전달합니다.forwardingTargetForSelector:

설정:

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

대리 대리인 :

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
    }  
}

이 대답은 진정한 Obj-C 스타일입니다!
Sound Blaster

forwardingTargetForSelector는 내가 알고 있었다면 과거 프로젝트에서 많은 시간을 절약 할 수 있었을 것입니다. 좋은 물건!
VaporwareWolf

4

Hunter Monk의 대답은 정말 대단하지만 안타깝게도 iOS 13.3.1에서는 작동하지 않습니다.

UINavigationBar잃지 않고 숨기는 또 다른 방법을 설명하겠습니다 swipe to back gesture. iOS 13.3.1 및 12.4.3에서 테스트했으며 작동합니다.

사용자 지정 클래스를 만들고 UINavigationController해당 클래스를 설정해야합니다 UINavigationController.Storyboard

사용자 정의 클래스를 <code> UINavigationController </ code>로 설정합니다.

숨기기하지 마십시오 NavigationBar온을Storyboard

<code> UINavigationController </ code> 속성 검사자 :

Storyboard:

스토리 보드 :

그리고 마지막으로,이를 넣어 : navigationBar.isHidden = true에서 viewDidLoadCustomNavigationController클래스입니다.

이 방법 setNavigationBarHidden(true, animated: true)을 사용 하여 NavigationBar.

import UIKit

class CustomNavigationController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationBar.isHidden = true
    }
}

2
실제 장치 iPhone 6S Plus에서 이것을 테스트 iOS 13.4.1하고 뒤로 스 와이프하여 작동합니다.
Emre Aydin

1
최신 iOS 14.0.1에서도 작동
bezoadam

1

Xamarin 답변 :

IUIGestureRecognizerDelegateViewController의 클래스 정의에서 인터페이스를 구현하십시오 .

public partial class myViewController : UIViewController, IUIGestureRecognizerDelegate

ViewController에서 다음 메소드를 추가하십시오.

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

ViewController ViewDidLoad()에 다음 줄을 추가하십시오.

NavigationController.InteractivePopGestureRecognizer.Delegate = this;

아마도 이것은 UINavigationController의 루트 뷰 컨트롤러에 있습니까? 나는 EXEC_BAD_ACCESS이것을 시도 할 때 얻는다 .
Benjohn 2015-09-30

루트 뷰 컨트롤러에서 에지 팬이 가능합니까? 루트 VC에있을 때 다른 모든 VC를 터 뜨리고 Nav의 VC 어레이의 길이가 1이어야하므로 가능하지 않습니다.
Ahmad

를 호출하기 전에 충돌이 발생합니다 gestureRecognizerShouldBegin:.
Benjohn 2015 년

1
새 질문 또는 Xamarin 포럼에 VC 코드를 게시 할 수 있습니까?
Ahmad

아뇨. .1로 남겨 둘 게요!
Benjohn

1

나는 이것을 시도했고 완벽하게 작동합니다 : 슬라이드 백 기능을 잃지 않고 탐색 모음을 숨기는 방법

아이디어는 .h에 "UIGestureRecognizerDelegate"를 구현하고이를 .m 파일에 추가하는 것입니다.

- (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;  
}

1

내 해결책은 다음과 같습니다. 탐색 모음에서 알파를 변경하고 있지만 탐색 모음이 숨겨져 있지 않습니다. 모든 뷰 컨트롤러는 BaseViewController의 하위 클래스이며 여기에 다음이 있습니다.

    override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    navigationController?.navigationBar.alpha = 0.0
}

UINavigationController를 하위 클래스로 만들고 해당 메서드를 거기에 둘 수도 있습니다.


0

일부 사람들 은 대신 setNavigationBarHiddenanimated로 메서드를 호출하여 성공했습니다 YES.


나는 운을 시도하지 않았다. 이 제안을 다루기 위해 내 답변을 업데이트합니다.
mihai

0

내비게이션 바가없는 내 뷰 컨트롤러에서

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

  CATransaction.begin()
  UIView.animate(withDuration: 0.25, animations: { [weak self] in
    self?.navigationController?.navigationBar.alpha = 0.01
  })
  CATransaction.commit()
}

open override func viewWillDisappear(_ animated: Bool) {
  super.viewWillDisappear(animated)
  CATransaction.begin()
  UIView.animate(withDuration: 0.25, animations: { [weak self] in
    self?.navigationController?.navigationBar.alpha = 1.0
  })
  CATransaction.commit()
}

대화식 해고 중에 뒤로 버튼이 빛나기 때문에 숨겼습니다.


-2

내가 시도하고 완벽하게 작동하는 정말 간단한 솔루션이 있습니다. 이것은 Xamarin.iOS에 있지만 네이티브에도 적용 할 수 있습니다.

    public override void ViewWillAppear(bool animated)
    {
        base.ViewWillAppear(animated);
        this.NavigationController.SetNavigationBarHidden(true, true);
    }

    public override void ViewDidAppear(bool animated)
    {
        base.ViewDidAppear(animated);
        this.NavigationController.SetNavigationBarHidden(false, false);
        this.NavigationController.NavigationBar.Hidden = true;
    }

    public override void ViewWillDisappear(bool animated)
    {
        base.ViewWillDisappear(animated);
        this.NavigationController.SetNavigationBarHidden(true, false);
    }

-6

다음은 사용자가 ViewController에서 슬라이드 할 때 제스처 인식기를 비활성화하는 방법입니다. viewWillAppear () 또는 ViewDidLoad () 메서드에 붙여 넣을 수 있습니다.

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

답변을 게시하기 전에 질문을 읽으십시오. 문제는 그것을 비활성화하는 것이 아니라 활성화하는 것이 었습니다. 우리는 팝 제스처를 좋아합니다.
Yogesh Maheshwari
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.