Wiem, że obecność kontrolera widoku more (paska nawigacji) powoduje obniżenie UIView o jego wysokość. Wiem też, że ta wysokość = 44px. Odkryłem również, że to wciśnięcie utrzymuje [self.view].frame.origin.y = 0
.
Jak więc określić wysokość tego paska nawigacji, inaczej niż tylko ustawiając go na stałą?
Lub, w przypadku krótszej wersji, jak ustalić, czy mój UIView jest wyświetlany z paskiem nawigacyjnym u góry?
Żarówka zaczęła się zapalać. Niestety nie znalazłem jednolitego sposobu rozwiązania problemu, jak opisano poniżej.
Uważam, że cały mój problem koncentruje się na moich automatycznych maskach. I powód, dla którego doszedłem do wniosku, że istnieją te same symptomy, z UIWebView lub bez niego. A symptomem tego jest to, że w przypadku Portretu wszystko jest brzoskwiniowe. W przypadku krajobrazu, najniżej położony UIButton pojawia się za TabBar.
Na przykład na jednym UIView mam, od góry do dołu:
UIView - zestaw obu sprężyn (przypadek domyślny) i brak rozpórek
UIScrollView - jeśli ustawię dwie sprężyny i wyczyszczę wszystko inne (jak UIView), wówczas UIButton wkracza na obiekt bezpośrednio nad nim. Jeśli wyczyszczę wszystko, to UIButton jest OK, ale rzeczy na samej górze chowają się za StatusBar Ustawiając tylko górną rozpórkę, UIButton wyskakuje za Tab Bar.
UILabel i UIImage obok w pionie - zestaw górnych rozpórek, elastyczny wszędzie indziej
Aby uzupełnić obraz dla nielicznych, którzy mają UIWebView:
UIWebView - Rozpórki: górna, lewa, prawa Sprężyny: obie
UIButton - nic nie jest ustawione, czyli wszędzie jest elastyczny
Chociaż moja żarówka jest przygaszona, wydaje się, że jest nadzieja.
Proszę o wyrozumiałość, ponieważ potrzebowałem więcej miejsca niż przewidziano na krótką odpowiedź na komentarz.
Dziękuję za próbę zrozumienia, na co tak naprawdę łowię ... więc proszę bardzo.
1) Każdy UIViewController (aplikacja TabBar) ma UIImage, jakiś tekst i cokolwiek na górze. Innym wspólnym mianownikiem jest przycisk UIB na dole. W przypadku niektórych UIViewControllers mam UIWebView powyżej UIButton.
A więc UIImage, tekst itp. UIWebView (na SOME) UIButton
Otaczający wszystko powyższe jest UIScrollView.
2) Dla tych, którzy mają UIWebView, jego autoresizeMask wygląda następująco:
—
|
—
^
|
|
| - | ← ---- → | - | | | V Maska UIButton nie ma nic ustawionego, tzn. Jest wszędzie elastyczna
W ramach my -viewDidLoad wywołuję moje -repositionSubViews, w ramach których wykonuję następujące czynności:
Jeśli nie ma UIWebView, nie robię nic poza wyśrodkowaniem UIButton, który umieściłem w IB.
Jeśli mam UIWebView, określam jego * zawartość * wysokość i ustawiam ramkę tak, aby obejmowała całą zawartość.
UIScrollView *scrollViewInsideWebView = [[webView_ subviews] lastObject];
webViewContentHeight = scrollViewInsideWebView.contentSize.height;
[webView_ setFrame:CGRectMake(webViewOriginX, webViewOriginY,
sameWholeViewScrollerWidth, webViewContentHeight)]
Kiedy to zrobię, programowo wciskam przycisk UIButton w dół, aby znalazł się poniżej UIWebView.
Wszystko działa, dopóki nie obrócę go z portretu na krajobraz.
Wywołuję moje -repositionSubViews w ramach mojego -didRotateFromInterfaceOrientation.
Dlaczego wysokość zawartości mojego UIWebView nie zmienia się wraz z obrotem?
Od pionowej do poziomej szerokość treści powinna się zwiększyć, a wysokość powinna się zmniejszyć. Robi wizualnie tak, jak powinien, ale nie według mojego NSLog.
W każdym razie, z lub bez UIWebView, przycisk, o którym mówiłem, przesuwa się poniżej paska TabBar w trybie poziomym, ale nie przewija się w górę, aby go zobaczyć. Widzę go za TabBarem, kiedy „energicznie” przewijam, ale potem „cofa się” za TabBar.
Podsumowując, to ostatnie jest powodem, dla którego zapytałem o wysokość TabBar i NavigationBar, ponieważ TabBar umieszcza się na dole UIView, a NavigationBar wypycha UIView w dół.
Teraz dodam tutaj komentarz lub dwa, ponieważ wcześniej nie miałyby one sensu.
Bez UIWebView zostawiam wszystko tak, jak widzi IB.
Za pomocą UIWebView zwiększam frame.height UIWebView do jego contentHeight, a także dostosowuję w górę wysokość otaczającego widoku UIScrollView, który otacza wszystkie widoki podrzędne.
Cóż, masz to.
W przypadku iPhone'a-X wysokość górnego paska (pasek nawigacji + pasek stanu) jest zmieniona (zwiększona).
Spróbuj tego, jeśli chcesz uzyskać dokładną wysokość górnego paska (zarówno pasek nawigacji + pasek stanu):
AKTUALIZACJA
iOS 13
Ponieważ
statusBarFrame
została wycofana wiOS13
, możesz użyć tego: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) } }
Cel C
CGFloat topbarHeight = ([UIApplication sharedApplication].statusBarFrame.size.height + (self.navigationController.navigationBar.frame.size.height ?: 0.0));
Szybki 4
let topBarHeight = UIApplication.shared.statusBarFrame.size.height + (self.navigationController?.navigationBar.frame.height ?? 0.0)
Dla ułatwienia wypróbuj to rozszerzenie UIViewController
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) } }
Szybki 3
let topBarHeight = UIApplication.sharedApplication().statusBarFrame.size.height + (self.navigationController?.navigationBar.frame.height ?? 0.0)
źródło
Wersja Swift :
let navigationBarHeight: CGFloat = self.navigationController!.navigationBar.frame.height
źródło
Próbowałeś tego?
let barHeight = self.navigationController?.navigationBar.frame.height ?? 0
źródło
Obsługa iOS 13 i poniżej:
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 } } }
źródło
UIApplication.shared.windows
keywnidow. (iOS 14)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 ); */
Więc jedyne, czego potrzebujemy, to
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;
źródło
Moja aplikacja ma kilka widoków, które wymagały dostosowania paska nawigacji w interfejsie użytkownika, aby wyglądać i działać, jednak bez kontrolera nawigacyjnego. A aplikacja jest wymagana do obsługi wersji iOS wcześniejszej niż iOS 11, więc nie można było korzystać z podręcznego przewodnika po bezpiecznym obszarze i muszę programowo dostosować pozycję i wysokość paska nawigacji.
Podłączyłem pasek nawigacji bezpośrednio do jego nadzoru, pomijając przewodnik po układzie bezpiecznego obszaru, jak wspomniano powyżej. Wysokość paska stanu można łatwo pobrać z UIApplication, ale domyślna wysokość paska nawigacji jest naprawdę uciążliwa ...
Uderzyło mnie przez prawie pół nocy, z wieloma poszukiwaniami i testami, aż w końcu dostałem wskazówkę z innego postu (choć nie działającego dla mnie), że tak naprawdę możesz uzyskać wysokość z UIView.sizeThatFits (), w ten sposób :
- (void)viewWillLayoutSubviews { self.topBarHeightConstraint.constant = [UIApplication sharedApplication].statusBarFrame.size.height; self.navBarHeightConstraint.constant = [self.navigationBar sizeThatFits:CGSizeZero].height; [super viewWillLayoutSubviews]; }
Wreszcie, doskonały pasek nawigacyjny wyglądający dokładnie tak samo jak wbudowany!
źródło
Jeśli chcesz uzyskać
navigationBar
tylko wysokość, jest to proste:extension UIViewController{ var navigationBarHeight: CGFloat { return self.navigationController?.navigationBar.frame.height ?? 0.0 } }
Jeśli jednak potrzebujesz wysokości górnej krawędzi iPhone'a, nie musisz pobierać
navigationBar
wysokości i dodawać do niejstatusBar
wysokości, możesz po prostu nazwaćsafeAreaInsets
to, dlaczego istnieje.self.view.safeAreaInsets.top
źródło
Szybki 5
Jeśli chcesz o rozważyć również safeArea:
let height = navigationController?.navigationBar.frame.maxY
źródło
Żarówka zaczęła się zapalać. Niestety nie znalazłem jednolitego sposobu rozwiązania problemu, jak opisano poniżej.
Uważam, że cały mój problem koncentruje się na moich automatycznych maskach. I powód, dla którego doszedłem do wniosku, że istnieją te same symptomy, z UIWebView lub bez niego. A symptomem tego jest to, że w przypadku Portretu wszystko jest brzoskwiniowe. W przypadku krajobrazu, najniżej położony UIButton pojawia się za TabBar.
Na przykład na jednym UIView mam, od góry do dołu:
UIView - zestaw obu sprężyn (przypadek domyślny) i brak rozpórek
UIScrollView - Jeśli ustawię dwie sprężyny i wyczyszczę wszystko inne (jak UIView), wówczas UIButton wkracza na obiekt bezpośrednio nad nim. Jeśli wszystko wyczyszczę, to UIButton jest OK, ale rzeczy na samej górze chowają się za StatusBar Ustawiając tylko górną rozpórkę, UIButton wyskakuje za paskiem Tab.
UILabel i UIImage obok w pionie - zestaw górnych rozpórek, elastyczny wszędzie indziej
Aby uzupełnić obraz dla nielicznych, którzy mają UIWebView:
UIWebView - Rozpórki: górna, lewa, prawa Sprężyny: obie
UIButton - nic nie jest ustawione, czyli wszędzie jest elastyczny
Chociaż moja żarówka jest przygaszona, wydaje się, że jest nadzieja.
źródło
Oto początek mojej odpowiedzi na Twoją aktualizację:
Czy to możliwe, ponieważ twoja automatyczna zmiana rozmiaru nie ma automatycznej maski zmiany rozmiaru dla wszystkich kierunków?
Jeszcze jedna sugestia, zanim wrócę po to, czy mógłbyś użyć paska narzędzi do swoich potrzeb. To trochę prostsze, zawsze będzie na dole, auto-rotacje / pozycje. Możesz to ukryć / pokazać do woli itp. Coś takiego: http://cdn.artoftheiphone.com/wp-content/uploads/2009/01/yellow-pages-iphone-app-2.jpg
Być może spojrzałeś na tę opcję, ale po prostu ją wyrzucił.
Inny pomysł, czy mógłbyś wykryć, z jakiej orientacji się obracasz, i po prostu programowo umieścić przycisk, aby dostosować się do paska kart. (Jest to możliwe za pomocą kodu)
źródło
Używałem:
let originY: CGFloat = self.navigationController!.navigationBar.frame.maxY
Działa świetnie, jeśli chcesz uzyskać wysokość paska nawigacji ORAZ jego początek Y.
źródło
Handy Swift 4 rozszerzenie, na wypadek gdyby było pomocne dla kogoś innego. Działa, nawet jeśli bieżący kontroler widoku nie wyświetla paska nawigacji.
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 } }
Stosowanie:
UINavigationController.navBarHeight()
źródło
iOS 14
Dla mnie
view.window
ma wartość NULL na iOS 14.extension UIViewController { var topBarHeight: CGFloat { var top = self.navigationController?.navigationBar.frame.height ?? 0.0 if #available(iOS 13.0, *) { top += UIApplication.shared.windows.first?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0 } else { top += UIApplication.shared.statusBarFrame.height } return top } }
źródło