Немає проведення пальцем назад, коли приховуєте панель навігації в UINavigationController


86

Мені подобається пакет розгорток, який успадкував від вбудовування ваших поглядів у 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, оскільки деякі люди кажуть, що це допомагає, але ще не змусило його працювати. Шукаєте тут найпростіше та найелегантніше рішення.
— mihai

Відповіді:


96

Працюючий хак полягає в тому, щоб встановити interactivePopGestureRecognizerделегата ', UINavigationControllerщоб nilвподобати це:

[self.navigationController.interactivePopGestureRecognizer setDelegate:nil];

Але в деяких ситуаціях це може створити дивні ефекти.


16
"Повторне проведення пальцем назад може спричинити розпізнавання жесту, коли у стеку є лише один контролер перегляду, який, у свою чергу, перетворює інтерфейс користувача (я вважаю це несподівано для інженерів UIKit), де він перестає розпізнавати будь-які жести"
— HorseT

4
Альтернатива , яка може захистити від несподіваного стану було б встановити його на який - небудь об'єкт низького рівня (я використовував моє додаток делегата) і здійснити gestureRecognizerShouldBegin, повертаючись , trueякщо navigationController«s viewControllerрахунки більше 0.
— Kenny Уінкер

4
Хоча це працює, ВИСОКО рекомендую проти цього. Поломка делегата спричинила рідкісний і важкий для ідентифікації головний блок потоку. Виявляється, це не основний блок потоку, а той, що описав @HorseT.
— Джош Бернфельд,

3
Мій додаток зберігає дескриптор делегування, а потім відновлює його, viewWillDisappearі до цього часу не відчував негативних побічних ефектів.
— Дон Парк

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
Найкраща відповідь, дякую!
— Дорі Даніель

2
@HunterMaximillionMonk дякую за чудове рішення. Це працює як шарм
— як diu

1
@HunterMaximillionMonk це, здається, працює правильно, але проблема з цим, коли у мене є кілька контролерів, після чого через один раз він перестає працювати.
— Премал Хетані,

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
— Бенджоном

2
Не забудьте додати UIGestureRecognizerDelegateдо кореневого контролера подання ... У моєму випадку делегатові було встановлено нуль у пізнішому контролері подання, ніж контролер кореневого перегляду, тому при поверненні до кореневого контролера подання gestureRecognizerShouldBeginне викликався. Таким чином , я помістив .delegate = selfв viewDidAppear(). Це вирішило дивні ефекти в моєму випадку .. Вітаємо!
— Wiingaard,

@AndreyGordeev Не могли б ви дати деякі подробиці про те, коли EXEC_BAD_ACCESSце відбувається?
— Jaybo

Ось додаткова інформація про EXC_BAD_ACCESSпомилку: stackoverflow.com/questions/28746123/…
— Андрій Гордєєв

25

Оновлено для iOS 13.4

iOS 13.4 зламав попереднє рішення, тому все стане неприємним. Схоже, в iOS 13.4 ця поведінка тепер контролюється приватним методом _gestureRecognizer:shouldReceiveEvent:(не плутати з новим загальнодоступним shouldReceiveметодом, доданим в iOS 13.4).


Я виявив, що інші опубліковані рішення, які перевизначають делегата, або встановлення його на нуль спричинили несподівану поведінку.

У моєму випадку, коли я знаходився на вершині стека навігації і намагався використати жест, щоб вивести ще один, він зазнав би невдачі (як і передбачалося), але подальші спроби натиснення на стек почали б викликати дивні графічні збої в панель навігації. Це має сенс, оскільки делегат використовується не лише для того, щоб заблокувати розпізнавання жесту, коли навігаційна панель прихована, і вся ця інша поведінка була викинута.

З мого тестування виявляється, що 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
Схоже, ваше рішення є найкращим на даний момент. Дякую!
— Тимур Бернікович

"але подальші спроби натиснути на стек почали б викликати дивні графічні збої в панелі навігації" - я тут збентежений. Я думав, у нас немає навігаційної панелі? Це питання? У моїй ситуації у мене є контролер навігації, вбудований як контролер дочірнього перегляду без панелі навігації; VC, що містить, має елементи керування навігацією. Отже, я дозволив вміщуючий ВК бути делегатом розпізнавача і щойно зробив gestureRecognizerShouldBegin:це, і це, здається, спрацьовує. Цікаво, чи варто мені пильнувати?
— skagedal 02

2
Це спричинило витік пам’яті, оскільки це navigationControllerбуло надійним посиланням у AlwaysPoppableDelegate. Я відредагував код, щоб зробити це weakпосиланням.
— Грем Перкс,

3
Це приємне рішення вже не працює в iOS 13.4
— Елі,

@ChrisVasselli Дійсно чудово, дякую! Сподіваємось, це пройде перевірку приватних методів огляду App Store.
— Елі,

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прокрутці.
— атулхатрі

Я виявив, що viewController.count> 1 перевірка необхідна. Якщо користувач намагається провести пальцем назад лише за допомогою кореневого VC, інтерфейс буде зависати при наступному натисканні VC.
— VaporwareWolf

11

Проста, без побічних ефектів відповідь

Хоча більшість відповідей тут хороші, вони, мабуть, мають ненавмисні побічні ефекти (розбиття додатків) або є багатослівними.

Найпростішим, але функціональним рішенням, яке я міг придумати, було наступне:

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

Інші відповіді пропонують просто встановити делегата на нуль. Проведення пальцем назад до початкового контролера перегляду в навігаційному стеку призводить до відключення всіх жестів. Можливо, якийсь нагляд за розробниками UIKit / UIGesture.

Крім того, деякі відповіді тут, які я реалізував, призвели до нестандартної поведінки навігації Apple (зокрема, дозволяючи можливість прокручувати вгору або вниз, а також проводячи назад). Ці відповіді також здаються дещо багатослівними, а в деяких випадках неповними.


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
Це правильне рішення. Будь-яке інше рішення, яке не пересилається оригінальному представнику, є неправильним.
— Джош Бернфельд,

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в viewDidLoadзCustomNavigationController класу.

Переконайтеся, що НЕ використовуйте цей метод 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і проведіть пальцем назад.
— Емре Айдін,

1
працює також на найновішій версії iOS 14.0.1
— bezoadam

1

Ксамарін Відповідь:

Реалізуйте IUIGestureRecognizerDelegateінтерфейс у визначенні класу ViewController:

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

Ви можете зробити панорамування краю на контролері кореневого перегляду? Це не повинно бути можливим, тому що коли ви знаходитесь у кореневому ВК, ви вискакуєте всі інші ВК, а довжина масиву ВК вашого Nav повинна бути 1.
— Ахмад,

Збій відбувається перед викликом gestureRecognizerShouldBegin:.
— Бенджон,

1
Чи можете ви розмістити свій код ВК в новому запитанні або на форумах Xamarin?
— Ахмад,

Ні, я ні. Думаю, залишу це на .1!
— Benjohn

1

Я спробував це, і воно працює чудово: як приховати панель навігації, не втрачаючи можливості повернення назад

Ідея полягає в тому, щоб реалізувати "UIGestureRecognizerDelegate" у своєму .h та додати це у свій .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

Деякі люди досягли успіху, викликавши setNavigationBarHiddenметод із анімованим 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;
}

Будь ласка, прочитайте питання перед тим, як розміщувати відповіді. Питання полягало в тому, щоб увімкнути його, а не вимкнути. МИ ЛЮБИМО ПОП-ЖЕСТ.
— Йогеш Махешварі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.