Secara terprogram mendapatkan ketinggian bilah navigasi


131

Saya tahu bahwa kehadiran lebih banyak pengontrol tampilan (bilah navigasi) menekan UIView dengan ketinggiannya. Saya juga tahu bahwa tinggi ini = 44px. Saya juga menemukan bahwa ini menekan mempertahankan [self.view].frame.origin.y = 0.

Jadi, bagaimana cara menentukan ketinggian bilah navigasi ini, selain hanya mengaturnya ke konstanta?

Atau, versi yang lebih pendek, bagaimana saya menentukan bahwa UIView saya ditampilkan dengan bilah navigasi di atas?


Bola lampu mulai menyala. Sayangnya, saya belum menemukan cara yang seragam untuk memperbaiki masalah, seperti dijelaskan di bawah ini.

Saya percaya bahwa seluruh masalah saya terpusat pada AutoresizingMasks saya. Dan alasan saya menyimpulkan bahwa ada gejala yang sama, dengan atau tanpa UIWebView. Dan gejala itu adalah bahwa segala sesuatu sangat bagus untuk Potret. Untuk Landscape, UIButton paling bawah muncul di belakang TabBar.

Misalnya, pada satu UIView, saya punya, dari atas ke bawah:

UIView - kedua pegas diatur (case default) dan tidak ada struts

UIScrollView - Jika saya mengatur dua pegas, dan menghapus semua yang lain (seperti UIView), maka UIButton mengganggu objek tepat di atasnya. Jika saya menghapus semuanya, maka UIButton OK, tetapi hal-hal di bagian paling atas bersembunyi di balik StatusBar Pengaturan hanya penyangga teratas, UIButton muncul di belakang Tab Bar.

UILabel dan UIImage selanjutnya vertikal - top strut set, fleksibel di mana pun

Hanya untuk melengkapi gambar untuk beberapa yang memiliki UIWebView:

UIWebView - Struts: atas, kiri, kanan Pegas: keduanya

UIButton - tidak ada yang ditetapkan, yaitu fleksibel di mana-mana

Meskipun bola lampu saya redup, tampaknya ada harapan.


Mohon bersabar karena saya membutuhkan lebih banyak ruang daripada yang disediakan untuk komentar balasan singkat.

Terima kasih telah mencoba memahami apa yang sebenarnya saya tangkap ... jadi begini.

1) Setiap UIViewController (aplikasi TabBar) memiliki UIImage, beberapa teks, dan apa pun di atasnya. Penyebut umum lainnya adalah tombol UIB di bagian bawah. Pada beberapa UIViewControllers saya memiliki UIWebView di atas UIButton.

Jadi, UIImage, teks dll. UIWebView (on BEBERAPA) UIButton

Yang mengelilingi semua di atas adalah UIScrollView.

2) Bagi yang memiliki UIWebView, autoresizingMask-nya terlihat seperti:

   
   |
   

   ^
   |
   |

| - | ← ---- → | - | | | V Topeng UIButton tidak memiliki set, yaitu fleksibel di mana-mana

Di dalam -viewDidLoad saya, saya memanggil -repositionSubViews tempat saya melakukan hal berikut:

Jika tidak ada UIWebView, saya tidak melakukan apa pun kecuali memusatkan UIButton yang saya tempatkan dengan IB.

Jika saya memiliki UIWebView, maka saya menentukan * konten * Tinggi dan mengatur bingkainya untuk melampirkan seluruh konten.

UIScrollView *scrollViewInsideWebView = [[webView_ subviews] lastObject];
webViewContentHeight = scrollViewInsideWebView.contentSize.height;
[webView_ setFrame:CGRectMake(webViewOriginX, webViewOriginY,
                          sameWholeViewScrollerWidth, webViewContentHeight)]

Setelah saya melakukan itu, maka saya secara pemrograman menekan tombol UIB ke bawah sehingga akhirnya ditempatkan di bawah UIWebView.

Semuanya berfungsi, sampai saya memutarnya dari Portrait ke Landscape.

Saya memanggil -reposisiSubViews saya dalam -didRotateFromInterfaceOrientation.

Mengapa ketinggian konten UIWebView saya tidak berubah dengan rotasi ?.

Dari Portrait ke Landscape, lebar konten harus membesar dan tinggi konten harus menyusut. Secara visual memang sebagaimana mestinya, tetapi tidak menurut NSLog saya.

Lagi pula, dengan atau tanpa UIWebView, tombol yang saya bicarakan bergerak di bawah TabBar ketika dalam mode Lansekap tetapi tidak akan menggulir ke atas untuk dilihat. Saya melihatnya di belakang TabBar ketika saya gulir "penuh semangat", tetapi kemudian "jatuh kembali" di belakang TabBar.

Intinya, yang terakhir ini adalah alasan saya bertanya tentang ketinggian TabBar dan NavigationBar karena TabBar menanam sendiri di bagian bawah UIView dan NavigationBar mendorong UIView ke bawah.

Sekarang, saya akan menambahkan satu atau dua komentar di sini karena mereka tidak akan masuk akal sebelumnya.

Tanpa UIWebView, saya membiarkan semuanya seperti yang terlihat oleh IB.

Dengan UIWebView, saya meningkatkan frame UIWebView. Tinggi ke contentHeight dan juga menyesuaikan ke atas ketinggian UIScrollView sekitarnya yang mengelilingi semua sub-tampilan.

Nah begitulah.

Jawaban:


258

Lakukan sesuatu seperti ini?

    NSLog(@"Navframe Height=%f",
        self.navigationController.navigationBar.frame.size.height);

Versi cepat terletak di sini


MEMPERBARUI

iOS 13

Karena statusBarFramesudah usang, iOS13Anda dapat menggunakan ini:

extension UIViewController {

    /**
     *  Height of status bar + navigation bar (if navigation bar exist)
     */

    var topbarHeight: CGFloat {
        return (view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0) +
            (self.navigationController?.navigationBar.frame.height ?? 0.0)
    }
}

Terima kasih terima kasih. TETAPI, setelah Anda menyelesaikan masalah itu, bagaimana cara menentukan apakah NavigationController, alias, MoreViewController, ditampilkan untuk aplikasi tab bar saya.

Saya tidak mengerti apa yang ingin Anda katakan. Apakah Anda mencoba mencari tahu apakah MoreViewController ditampilkan? (Jika demikian, apa yang ingin Anda lakukan?) Dan jika tidak, dapatkah Anda menjelaskan apa yang sebenarnya Anda maksud?
Jumlah

Saya membaca pertanyaan Anda lagi, dan saya masih tidak mengerti apa yang ingin Anda lakukan? Jika Anda ingin melakukan sesuatu ketika tampilan muncul, Anda harus memasukkan kode ke viewDidAppear. Jika Anda mengklarifikasi sedikit, akan lebih mudah untuk menentukan apa yang ingin Anda lakukan.
Jumlah

2
Saya tahu ini tidak menjawab pertanyaan yang diajukannya, tetapi sepertinya dia mencari untuk melihat apakah navigationBar disembunyikan atau tidak. Jika demikian, ia bisa menggunakan self.navigationController.navigationBarHidden Hope sepenuhnya ini membantu seseorang :)
taylorcressy

2
Di iOS 7+ Anda mungkin perlu mempertimbangkan bilah status 20px tergantung pada aplikasi Anda
Slayter

94

Dengan iPhone-X, ketinggian bilah atas (bilah navigasi + bilah status) diubah (meningkat).

Coba ini jika Anda ingin ketinggian bar bagian atas (kedua bar navigasi + status bar):

MEMPERBARUI

iOS 13

Karena statusBarFramesudah usang, iOS13Anda dapat menggunakan ini:

extension UIViewController {

    /**
     *  Height of status bar + navigation bar (if navigation bar exist)
     */

    var topbarHeight: CGFloat {
        return (view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0) +
            (self.navigationController?.navigationBar.frame.height ?? 0.0)
    }
}

Objektif-C

CGFloat topbarHeight = ([UIApplication sharedApplication].statusBarFrame.size.height +
       (self.navigationController.navigationBar.frame.size.height ?: 0.0));

Cepat 4

let topBarHeight = UIApplication.shared.statusBarFrame.size.height +
        (self.navigationController?.navigationBar.frame.height ?? 0.0)

Untuk memudahkan, coba ekstensi UIViewController ini

extension UIViewController {

    /**
     *  Height of status bar + navigation bar (if navigation bar exist)
     */

    var topbarHeight: CGFloat {
        return UIApplication.shared.statusBarFrame.size.height +
            (self.navigationController?.navigationBar.frame.height ?? 0.0)
    }
}

Cepat 3

let topBarHeight = UIApplication.sharedApplication().statusBarFrame.size.height +
(self.navigationController?.navigationBar.frame.height ?? 0.0)


3
Jawaban Swift 4 mengembalikan tinggi 0 untuk saya.
Chewie The Chorkie

61

Swift versi:

let navigationBarHeight: CGFloat = self.navigationController!.navigationBar.frame.height

Selalu mengembalikan 44. Bagaimana mengetahui ukuran diciutkan (44) atau ukuran diperluas (judul besar) ??? Secara dinamis, tentu saja. (Saya tahu apa ukurannya)
Markus

6

Apakah kamu mencoba ini?

let barHeight = self.navigationController?.navigationBar.frame.height ?? 0

5

Mendukung iOS 13 dan Bawah:

extension UIViewController {

    var topbarHeight: CGFloat {
        if #available(iOS 13.0, *) {
            return (view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0.0) +
                (self.navigationController?.navigationBar.frame.height ?? 0.0)
        } else {
            let topBarHeight = UIApplication.shared.statusBarFrame.size.height +
            (self.navigationController?.navigationBar.frame.height ?? 0.0)
            return topBarHeight
        }
    }
}

4
UIImage*image = [UIImage imageNamed:@"logo"];

float targetHeight = self.navigationController.navigationBar.frame.size.height;
float logoRatio = image.size.width / image.size.height;
float targetWidth = targetHeight * logoRatio;

UIImageView*logoView = [[UIImageView alloc] initWithImage:image];
// X or Y position can not be manipulated because autolayout handles positions.
//[logoView setFrame:CGRectMake((self.navigationController.navigationBar.frame.size.width - targetWidth) / 2 , (self.navigationController.navigationBar.frame.size.height - targetHeight) / 2 , targetWidth, targetHeight)];
[logoView setFrame:CGRectMake(0, 0, targetWidth, targetHeight)];
self.navigationItem.titleView = logoView;

// How much you pull out the strings and struts, with autolayout, your image will fill the width on navigation bar. So setting only height and content mode is enough/
[logoView setContentMode:UIViewContentModeScaleAspectFit];

/* Autolayout constraints also can not be manipulated since navigation bar has  immutable constraints
self.navigationItem.titleView.translatesAutoresizingMaskIntoConstraints = false;

NSDictionary*metricsArray = @{@"width":[NSNumber numberWithFloat:targetWidth],@"height":[NSNumber numberWithFloat:targetHeight],@"margin":[NSNumber numberWithFloat:20]};
NSDictionary*viewsArray = @{@"titleView":self.navigationItem.titleView};

[self.navigationItem.titleView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-(>margin=)-H:[titleView(width)]-(>margin=)-|" options:NSLayoutFormatAlignAllCenterX metrics:metricsArray views:viewsArray]];
[self.navigationItem.titleView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[titleView(height)]" options:0 metrics:metricsArray views:viewsArray]];

NSLog(@"%f", self.navigationItem.titleView.width );
*/

Jadi sebenarnya yang kita butuhkan adalah

UIImage*image = [UIImage imageNamed:@"logo"];
UIImageView*logoView = [[UIImageView alloc] initWithImage:image];
float targetHeight = self.navigationController.navigationBar.frame.size.height;
[logoView setFrame:CGRectMake(0, 0, 0, targetHeight)];
[logoView setContentMode:UIViewContentModeScaleAspectFit];

self.navigationItem.titleView = logoView;

2

Aplikasi saya memiliki beberapa tampilan yang memerlukan bilah navigasi khusus di UI untuk tampilan & nuansa, namun tanpa pengontrol navigasi. Dan aplikasi ini diperlukan untuk mendukung versi iOS sebelum iOS 11, sehingga panduan tata letak area aman yang praktis tidak dapat digunakan, dan saya harus menyesuaikan posisi dan ketinggian bilah navigasi secara terprogram.

Saya memasang Bilah Navigasi ke superview secara langsung, melewatkan panduan tata letak area aman seperti yang disebutkan di atas. Dan ketinggian bilah status dapat diambil dari aplikasi UIA dengan mudah, tetapi ketinggian bilah navigasi standar benar-benar ...

Saya tersadar hampir setengah malam, dengan sejumlah pencarian dan pengujian, sampai saya akhirnya mendapatkan petunjuk dari pos lain (meskipun tidak bekerja untuk saya), bahwa Anda benar-benar bisa mendapatkan ketinggian dari UIView.sizeThatFits (), seperti ini :

- (void)viewWillLayoutSubviews {
    self.topBarHeightConstraint.constant = [UIApplication sharedApplication].statusBarFrame.size.height;
    self.navBarHeightConstraint.constant = [self.navigationBar sizeThatFits:CGSizeZero].height;

    [super viewWillLayoutSubviews];    
}

Terakhir, bilah navigasi sempurna yang persis sama dengan bilah bawaan!


2

Jika Anda ingin mendapatkan navigationBarketinggian saja, sederhana:

extension UIViewController{
   var navigationBarHeight: CGFloat {
       return self.navigationController?.navigationBar.frame.height ?? 0.0
   }
}

Namun, jika Anda membutuhkan tinggi kedudukan tertinggi iPhone Anda tidak perlu mendapatkan navigationBartinggi dan menambah statusBartinggi, Anda dapat memanggil safeAreaInsetsitu sebabnya ada.

self.view.safeAreaInsets.top

1

Bola lampu mulai menyala. Sayangnya, saya belum menemukan cara yang seragam untuk memperbaiki masalah, seperti dijelaskan di bawah ini.

Saya percaya bahwa seluruh masalah saya terpusat pada AutoresizingMasks saya. Dan alasan saya menyimpulkan bahwa ada gejala yang sama, dengan atau tanpa UIWebView. Dan gejala itu adalah bahwa segala sesuatu sangat bagus untuk Potret. Untuk Landscape, UIButton paling bawah muncul di belakang TabBar.

Misalnya, pada satu UIView, saya punya, dari atas ke bawah:

UIView - kedua pegas diatur (case default) dan tidak ada struts

UIScrollView - Jika saya mengatur dua pegas, dan menghapus semua yang lain (seperti UIView), maka UIButton mengganggu objek tepat di atasnya. Jika saya menghapus semuanya, maka UIButton OK, tetapi hal-hal di bagian paling atas bersembunyi di balik StatusBar Pengaturan hanya penyangga teratas, UIButton muncul di belakang Tab Bar.

UILabel dan UIImage selanjutnya vertikal - top strut set, fleksibel di mana pun

Hanya untuk melengkapi gambar untuk beberapa yang memiliki UIWebView:

UIWebView - Struts: atas, kiri, kanan Pegas: keduanya

UIButton - tidak ada yang ditetapkan, yaitu fleksibel di mana-mana

Meskipun bola lampu saya redup, tampaknya ada harapan.


Atur top strut dan atur dua pegas dari UIWebView - masalah terpecahkan dan terima kasih banyak. Sebagai soal fakta, satu-satunya masalah saya yang tersisa adalah mendesain grafis terkutuk @ 2X, dll. Saya menggunakan GraphicConverter dengan cara yang sangat sederhana dan berfungsi dengan baik untuk desain Halaman Web, dengan sangat baik. Tetapi semua hal 30px, 57px ini - setidaknya saya akan pergi ke wilayah yang belum dipetakan.

1

Inilah awal tanggapan saya terhadap pembaruan Anda:

Mengapa ketinggian konten UIWebView saya tidak berubah dengan rotasi ?.

Mungkinkah karena ukuran otomatis Anda tidak memiliki autoresizingMask untuk semua arah?

Saran lain sebelum saya kembali untuk ini, dapatkah Anda menggunakan toolbar untuk kebutuhan Anda. Ini sedikit lebih sederhana, akan selalu di bagian bawah, otomatis berputar / posisi. Anda dapat menyembunyikan / menampilkannya sesuka hati dll. Jenis seperti ini: http://cdn.artoftheiphone.com/wp-content/uploads/2009/01/yellow-pages-iphone-app-2.jpg

Anda mungkin telah melihat opsi itu, tetapi hanya membuangnya di sana.

Gagasan lain, dapatkah Anda mendeteksi orientasi yang Anda putar, dan letakkan tombol secara terprogram untuk menyesuaikan bilah tab. (Ini mungkin dengan kode)


Setelah sekitar 2 minggu menangani masalah ini, saya memutuskan bahwa "masalah" menjadi lebih sulit dengan menempatkan UIButton DI BAWAH sub-tampilan UIWebView. Jadi, saya meletakkan tombol di atasnya. Sejujurnya, itu tidak terlihat "benar" seperti itu ... tetapi sekarang berfungsi SORT OF. DI BAWAH atau DI ATAS UIWebView telah menetapkan penyangga atas dan hanya pegas horizontal. BTW, ini contentHeight dari UIWebView yang tidak berubah dengan rotasi.

0

Saya telah menggunakan:

let originY: CGFloat = self.navigationController!.navigationBar.frame.maxY

Bekerja dengan baik jika Anda ingin mendapatkan ketinggian bilah navigasi DAN asal Y-nya.


0

Cepat 5

Jika Anda ingin mempertimbangkan safeArea juga:

 let height = navigationController?.navigationBar.frame.maxY  

0

Ekstensi Handy Swift 4, jika bermanfaat bagi orang lain. Bekerja bahkan jika pengontrol tampilan saat ini tidak menampilkan bilah navigasi.

import UIKit

extension UINavigationController {
  static public func navBarHeight() -> CGFloat {
    let nVc = UINavigationController(rootViewController: UIViewController(nibName: nil, bundle: nil))
    let navBarHeight = nVc.navigationBar.frame.size.height
    return navBarHeight
  }
}

Pemakaian:

UINavigationController.navBarHeight()
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.