Tidak Ada Gesek Kembali saat menyembunyikan Bilah Navigasi di UINavigationController

86

Saya suka paket gesek yang diwarisi dari menyematkan pandangan Anda dalam file UINavigationController. Sayangnya saya tidak dapat menemukan cara untuk menyembunyikannya NavigationBartetapi masih memiliki touch pan swipe back gesture. Saya dapat menulis gerakan khusus tetapi saya memilih untuk tidak melakukannya dan sebagai gantinya mengandalkan UINavigationControllergesekan ke belakang gesture.

jika saya hapus centang di storyboard, geser ke belakang tidak berfungsi

masukkan deskripsi gambar di sini

sebagai alternatif jika saya secara terprogram menyembunyikannya, skenario yang sama.

Apakah tidak ada cara untuk menyembunyikan bagian atas NavigationBardan masih memiliki gesekan?

mihai
sumber
1
Apakah menambahkan UIGestureRecognizer dapat diterima? Sangat mudah untuk diterapkan.
SwiftArchitect
1
@LancelotdelaMare, saya mencoba menghindarinya karena tidak akan bekerja semulus usapan kembali UINavigationController. Saya melihat ke UIScreenEdgePanGestureRecognizer karena beberapa orang mengatakan ini membantu tetapi belum berhasil. Mencari solusi paling sederhana dan elegan di sini.
mihai

Jawaban:

98

Sebuah hack yang berhasil adalah mengatur interactivePopGestureRecognizerdelegasi UINavigationControllermenjadi nilseperti ini:

[self.navigationController.interactivePopGestureRecognizer setDelegate:nil];

Tetapi dalam beberapa situasi hal itu dapat menimbulkan efek aneh.

KudaT
sumber
16
"menggesek ke belakang berulang kali dapat menyebabkan isyarat dikenali saat hanya ada satu pengontrol tampilan di tumpukan, yang pada gilirannya menempatkan UI dalam keadaan (menurut saya tidak terduga oleh teknisi UIKit) di mana ia berhenti mengenali isyarat apa pun"
HorseT
4
Sebuah alternatif yang mungkin melindungi terhadap keadaan yang tak terduga akan mengaturnya untuk beberapa objek tingkat rendah (saya menggunakan delegasi app saya) dan melaksanakan gestureRecognizerShouldBegin, kembali truejika navigationController's viewControllerhitung lebih besar dari 0
Kenny Winker
4
Meskipun ini berhasil, saya SANGAT merekomendasikan untuk tidak melakukannya. Melanggar delegasi menyebabkan blok utas utama yang langka dan sulit diidentifikasi. Ternyata ini bukan blok utas utama tetapi itu yang dijelaskan @HorseT.
Josh Bernfeld
3
Aplikasi saya menyimpan pegangan delegasi kemudian mengembalikannya viewWillDisappeardan sejauh ini tidak mengalami efek samping yang merugikan.
Don Park
1
!!!! Sangat tidak disarankan untuk menggunakan solusi ini, ketika berulang kali menggunakan gesekan, perilaku aneh terjadi, bagian belakang dinonaktifkan dan seluruh aplikasi tidak merespons lagi
KarimIhab
81

Masalah dengan Metode Lain

Pengaturan interactivePopGestureRecognizer.delegate = nilmemiliki efek samping yang tidak diinginkan.

Pengaturan navigationController?.navigationBar.hidden = trueberfungsi, tetapi tidak memungkinkan perubahan Anda di bilah navigasi disembunyikan.

Terakhir, umumnya praktik yang lebih baik adalah membuat objek model UIGestureRecognizerDelegateuntuk pengontrol navigasi Anda. Menyetelnya ke pengontrol di UINavigationControllertumpukan inilah yang menyebabkan EXC_BAD_ACCESSkesalahan.

Solusi Lengkap

Pertama, tambahkan kelas ini ke proyek Anda:

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

Kemudian, setel pengontrol navigasi Anda interactivePopGestureRecognizer.delegateke instance InteractivePopRecognizerkelas baru Anda .

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
}

Nikmati bilah navigasi tersembunyi tanpa efek samping, yang berfungsi bahkan jika pengontrol teratas Anda memiliki subview tampilan tabel, koleksi, atau tampilan gulir.

Hunter Monk
sumber
2
Solusi bagus!
Matt Butler
2
Jawaban terbaik, Terima kasih!
Dory Daniel
3
@HunterMaximillionMonk terima kasih atas solusi hebatnya. Ini bekerja seperti pesona
seperti diu
2
Jawaban yang pasti terbaik!
daxh
2
Bekerja di iOS 13.5, 12.4.6 dan 10.3.4. Terima kasih.
Денис Попов
55

Dalam kasus saya, untuk mencegah efek aneh

Pengontrol tampilan root

override func viewDidLoad() {
    super.viewDidLoad()

    // Enable swipe back when no navigation bar
    navigationController?.interactivePopGestureRecognizer?.delegate = self
}

// UIGestureRecognizerDelegate
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    if let navVc = navigationController {
      return navVc.viewControllers.count > 1
    }
    return false
}
saranpol
sumber
2
Kadang-kadang saya mendapatkan EXC_BAD_ACCESS saat menggunakan ini
Andrey Gordeev
Bagi saya, itu tidak membuat isyarat berhasil dan sering menabrakEXEC_BAD_ACCESS
Benjohn
2
Ingatlah untuk menambahkan UIGestureRecognizerDelegateke pengontrol tampilan root ... Dalam kasus saya, delegasi disetel ke nihil di pengontrol tampilan yang lebih baru daripada pengontrol tampilan root, jadi ketika kembali ke pengontrol tampilan root, gestureRecognizerShouldBegintidak dipanggil. Jadi saya menempatkannya .delegate = selfdi viewDidAppear(). Itu memecahkan efek aneh dalam kasusku .. Cheers!
Wiingaard
@AndreyGordeev Bisakah Anda memberikan beberapa rincian tentang kapan EXEC_BAD_ACCESSterjadi?
Jaybo
Berikut info lebih lanjut tentang EXC_BAD_ACCESSkesalahan: stackoverflow.com/questions/28746123/…
Andrey Gordeev
25

Diperbarui untuk iOS 13.4

iOS 13.4 merusak solusi sebelumnya, jadi semuanya akan menjadi buruk. Sepertinya di iOS 13.4 perilaku ini sekarang dikontrol dengan metode privat _gestureRecognizer:shouldReceiveEvent:(jangan disamakan dengan shouldReceivemetode publik baru yang ditambahkan di iOS 13.4).


Saya menemukan bahwa solusi lain yang diposting mengesampingkan delegasi, atau menyetelnya ke nol menyebabkan beberapa perilaku yang tidak terduga.

Dalam kasus saya, ketika saya berada di atas tumpukan navigasi dan mencoba menggunakan isyarat untuk memunculkan satu lagi, itu akan gagal (seperti yang diharapkan), tetapi upaya selanjutnya untuk mendorong ke tumpukan akan mulai menyebabkan gangguan grafis aneh di bilah navigasi. Ini masuk akal, karena delegasi digunakan untuk menangani lebih dari sekedar apakah akan memblokir isyarat agar tidak dikenali saat bilah navigasi disembunyikan, dan semua perilaku lain itu dibuang.

Dari pengujian saya, tampaknya itu gestureRecognizer(_:, shouldReceiveTouch:)adalah metode yang diterapkan oleh delegasi asli untuk memblokir isyarat agar tidak dikenali saat bilah navigasi disembunyikan, bukan gestureRecognizerShouldBegin(_:). Solusi lain yang diimplementasikan gestureRecognizerShouldBegin(_:)dalam pekerjaan delegasi mereka karena kurangnya implementasi gestureRecognizer(_:, shouldReceiveTouch:)akan menyebabkan perilaku default menerima semua sentuhan.

Solusi @Nathan Perry semakin dekat, tetapi tanpa implementasi respondsToSelector(_:), kode UIKit yang mengirimkan pesan ke delegasi akan percaya bahwa tidak ada implementasi untuk metode delegasi lainnya, dan forwardingTargetForSelector(_:)tidak akan pernah dipanggil.

Jadi, kami mengontrol `gestureRecognizer (_ :, shouldReceiveTouch :) dalam satu skenario tertentu yang ingin kami ubah perilakunya, dan sebaliknya meneruskan yang lainnya ke delegasi.

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
        }
    }
}
Chris Vasselli
sumber
1
Sepertinya solusi Anda adalah yang terbaik untuk saat ini. Terima kasih!
Timur Bernikovich
"tetapi upaya berikutnya untuk mendorong ke tumpukan akan mulai menyebabkan gangguan grafis yang aneh di bilah navigasi" - Saya bingung di sini. Saya pikir kami tidak memiliki bilah navigasi? Itu pertanyaannya? Dalam situasi saya, saya memiliki pengontrol navigasi yang disematkan sebagai pengontrol tampilan anak tanpa navbar; VC yang berisi memiliki kontrol navigasi. Jadi saya telah membiarkan VC yang berisi menjadi delegasi pengenal dan hanya melakukan gestureRecognizerShouldBegin:hal itu, dan "tampaknya berhasil". Ingin tahu apakah saya harus berhati-hati.
skagedal
2
Ini memiliki kebocoran memori karena navigationControllermerupakan referensi yang kuat di AlwaysPoppableDelegate. Saya telah mengedit kode untuk menjadikannya sebagai weakreferensi.
Graham Perks
3
Solusi bagus ini tidak berfungsi lagi di iOS 13.4
Ely
@ChrisVasselli Benar-benar luar biasa, terima kasih! Semoga ini akan melewati pemeriksaan metode pribadi dari ulasan App Store.
Ely
16

Anda dapat membuat subkelas UINavigationController sebagai berikut:

@interface CustomNavigationController : UINavigationController<UIGestureRecognizerDelegate>

@end

Penerapan:

@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
Yogesh Maheshwari
sumber
2
Menggunakan pendekatan ini melanggar gerakan pop saat UIPageViewControllermenggulung.
atulkhatri
Saya menemukan bahwa viewController.count> 1 pemeriksaan diperlukan. Jika pengguna mencoba untuk menggesek kembali dengan hanya VC root, UI akan bertahan pada dorongan VC berikutnya.
VaporwareWolf
12

Sederhana, tanpa efek samping. Jawaban

Meskipun sebagian besar jawaban di sini bagus, namun tampaknya memiliki efek samping yang tidak diinginkan (kerusakan aplikasi) atau bertele-tele.

Solusi paling sederhana namun fungsional yang dapat saya hasilkan adalah sebagai berikut:

Di ViewController tempat Anda menyembunyikan navigationBar,

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

Jawaban lain menyarankan hanya menetapkan delegasi ke nol. Menggeser ke belakang ke pengontrol tampilan awal di tumpukan navigasi akan membuat semua gerakan dinonaktifkan. Semacam pengawasan, mungkin, dari pengembang UIKit / UIGesture.

Selain itu, beberapa jawaban di sini yang telah saya terapkan menghasilkan perilaku navigasi apel non-standar (khususnya, memungkinkan kemampuan untuk menggulir ke atas atau ke bawah sambil juga menggesek ke belakang). Jawaban ini juga tampak sedikit bertele-tele dan dalam beberapa kasus tidak lengkap.

CodyB
sumber
viewDidLoad()bukan tempat yang baik untuk menangkap initialInteractivePopGestureRecognizerDelegatekarena navigationControllermungkin nihil di sana (belum didorong ke tumpukan). viewWillAppeardari tempat di mana Anda menyembunyikan bilah navigasi akan lebih sesuai
nCod3d
10

Berdasarkan jawaban Hunter Maximillion Monk , saya membuat subclass untuk UINavigationController dan kemudian mengatur kelas kustom untuk UINavigationController saya di storyboard saya. Kode akhir untuk kedua kelas terlihat seperti ini:

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

Papan cerita:

Kelas kustom pengontrol navigasi storyboard

tylermilner.dll
sumber
8

Sepertinya solusi yang diberikan oleh @ChrisVasseli adalah yang terbaik. Saya ingin memberikan solusi yang sama di Objective-C karena pertanyaannya adalah tentang Objective-C (lihat tag)

@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
Timur Bernikovich
sumber
3
Karena ObjC belum mati! 😉
MonsieurDart
2
Ini adalah solusi yang tepat. Solusi lain yang tidak meneruskan ke delegasi asli tidak benar.
Josh Bernfeld
6

Solusi saya adalah dengan langsung memperluas UINavigationControllerkelas:

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
    }

}

Dengan cara ini, semua pengontrol navigasi akan dapat ditutup dengan menggeser.

fredericdnd
sumber
Anehnya hal ini menyebabkan semua viewDidAppearpanggilan di VC milik pengontrol navigasi apa pun diabaikan.
cumanzor
4

Anda dapat melakukannya dengan Proxy Delegate. Saat Anda membuat pengontrol navigasi, ambil delegasi yang ada. Dan berikan ke proxy. Kemudian teruskan semua metode delegasi ke delegasi yang ada kecuali gestureRecognizer:shouldReceiveTouch:menggunakanforwardingTargetForSelector:

Mendirikan:

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

Delegasi Proksi:

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
    }  
}
Nathan Perry
sumber
Jawaban ini benar gaya Obj-C!
Sound Blaster
forwardingTargetForSelector akan menghemat begitu banyak waktu saya pada proyek sebelumnya jika saya mengetahuinya. Barang bagus!
VaporwareWolf
4

Jawaban Hunter Monk benar-benar luar biasa, tetapi sayangnya di iOS 13.3.1, itu tidak berfungsi.

Saya akan menjelaskan cara lain untuk bersembunyi UINavigationBardan tidak kalahswipe to back gesture . Saya telah menguji di iOS 13.3.1 dan 12.4.3 dan berhasil.

Anda perlu membuat kelas khusus UINavigationControllerdan mengatur kelas itu untuk UINavigationControllerdiStoryboard

Setel kelas khusus ke <code> UINavigationController </code>

JANGAN sembunyikan NavigationBardiStoryboard

<code> UINavigationController </code> Attributes inspector:

Contoh di Storyboard:

Papan cerita:

Dan akhirnya, masukkan ini: navigationBar.isHidden = truedi viewDidLoaddalamCustomNavigationController kelas.

Pastikan, JANGAN gunakan metode ini setNavigationBarHidden(true, animated: true)untuk menyembunyikan file NavigationBar.

import UIKit

class CustomNavigationController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationBar.isHidden = true
    }
}
Jusuf Saiti
sumber
2
Saya telah menguji ini di perangkat asli iPhone 6S Plus dengan iOS 13.4.1dan geser kembali berfungsi.
Emre Aydin
1

Xamarin Jawaban:

Implementasikan IUIGestureRecognizerDelegateAntarmuka dalam definisi Kelas ViewController Anda:

public partial class myViewController : UIViewController, IUIGestureRecognizerDelegate

Di ViewController Anda, tambahkan metode berikut:

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

Di ViewController Anda, ViewDidLoad()tambahkan baris berikut:

NavigationController.InteractivePopGestureRecognizer.Delegate = this;
Ahmad
sumber
Mungkin ini ada di UINavigationControllerpengontrol tampilan root? Saya mengerti EXEC_BAD_ACCESSketika saya mencoba ini.
Benjohn
Anda dapat melakukan edge pan pada pengontrol tampilan root? Itu seharusnya tidak mungkin karena ketika Anda berada di root VC, Anda telah memunculkan semua VC lainnya, dan panjang array VC Nav Anda harus 1.
Ahmad
Kecelakaan terjadi sebelum panggilan ke gestureRecognizerShouldBegin:.
Benjohn
1
Dapatkah Anda memposting kode VC Anda di Pertanyaan baru atau di forum Xamarin?
Ahmad
Tidak, saya belum. Saya pikir saya akan meninggalkannya untuk .1!
Benjohn
1

Saya sudah mencoba ini dan berfungsi dengan sempurna: Cara menyembunyikan Bilah Navigasi tanpa kehilangan kemampuan geser ke belakang

Idenya adalah untuk mengimplementasikan "UIGestureRecognizerDelegate" di .h Anda dan menambahkan ini ke file .m Anda.

- (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;  
}
KarimIhab
sumber
1

Inilah solusi saya: Saya mengubah alfa pada bilah navigasi, tetapi bilah navigasi tidak tersembunyi. Semua pengontrol tampilan saya adalah subkelas dari BaseViewController saya, dan di sana saya memiliki:

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

Anda juga bisa membuat subkelas UINavigationController dan meletakkan metode itu di sana.

Mladen Ivastinovic
sumber
0

Beberapa orang telah berhasil dengan memanggil setNavigationBarHiddenmetode animasi YESsebagai gantinya.

Mundi
sumber
Saya mencoba tidak berhasil. Memperbarui jawaban saya untuk menutupi saran ini.
mihai
0

Dalam pengontrol tampilan saya tanpa bilah navigasi yang saya gunakan

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

Selama penutupan interaktif, tombol kembali akan bersinar, itulah sebabnya saya menyembunyikannya.

pembuat buah
sumber
-2

Ada solusi yang sangat sederhana yang saya coba dan berfungsi dengan sempurna, ini ada di Xamarin.iOS tetapi dapat diterapkan ke native juga:

    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);
    }
João Palma
sumber
-6

Berikut adalah cara menonaktifkan pengenal de gestur saat pengguna keluar dari ViewController. Anda dapat menempelkannya di viewWillAppear () atau pada metode ViewDidLoad () Anda.

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
Eddwin Paz
sumber
Harap baca pertanyaan sebelum memposting jawaban. Pertanyaannya adalah tentang mengaktifkannya, bukan menonaktifkannya. KAMI MENYUKAI GESTUR POP.
Yogesh Maheshwari