programing tip

프로그래밍 방식으로 탐색 막대의 높이를 얻습니다.

itbloger 2020. 7. 13. 21:39
반응형

프로그래밍 방식으로 탐색 막대의 높이를 얻습니다.


더 많은 뷰 컨트롤러 (탐색 표시 줄)가 있으면 UIView가 높이로 내려갑니다. 또한이 높이 = 44px임을 알고 있습니다. 나는 또한이 푸시 다운이를 유지한다는 것을 발견했다 [self.view].frame.origin.y = 0.

그렇다면이 탐색 막대의 높이를 상수로 설정하는 것 외에는 어떻게 결정합니까?

또는 더 짧은 버전의 경우 내 UIView가 탐색 막대와 함께 표시되는지 어떻게 알 수 있습니까?


전구가 켜지 기 시작했습니다. 불행히도 아래 설명과 같이 문제를 해결하는 획일적 인 방법을 찾지 못했습니다.

나는 내 모든 문제가 내 자동 크기 조정 마스크에 집중되어 있다고 생각합니다. 그리고 UIWebView의 유무에 관계없이 동일한 증상이 있다고 결론 내린 이유. 그리고 그 증상은 모든 것이 초상화에 복숭아 색이라는 것입니다. Landscape의 경우 맨 아래 UIButton이 TabBar 뒤에 나타납니다.

예를 들어 하나의 UIView에서 위에서 아래로 있습니다.

UIView – 스프링 설정 (기본 경우) 및 스트럿 없음

UIScrollView-두 개의 스프링을 설정하고 UIView와 같은 다른 모든 항목을 지우면 UIButton이 바로 위에있는 객체에 침입합니다. 모든 것을 지우면 UIButton은 정상이지만 맨 위에있는 것은 StatusBar 뒤에 숨겨지고 UI 스트럿은 Tab Bar 뒤에 나타납니다.

UILabel과 UIImage는 다음 수직 방향 – 상단 스트럿 세트, 다른 곳에서도 유연

UIWebView가있는 몇 가지 그림을 완성하십시오.

UIWebView-스트럿 : 위, 왼쪽, 오른쪽 스프링 : 둘 다

UIButton – 아무것도 설정되지 않음, 즉 어디에서나 유연

전구가 희미하지만 희망이있는 것 같습니다.


짧은 답글 코멘트에 제공된 것보다 더 많은 공간이 필요했기 때문에 저와 함께 해주십시오.

내가 정말로 낚시하는 것을 이해하려고 노력해 주셔서 감사합니다 ... 그래서 여기에갑니다.

1) 각 UIViewController (TabBar 앱)에는 UIImage, 일부 텍스트 및 그 밖의 모든 것이 있습니다. 또 다른 공통 분모는 맨 아래에있는 UIButton입니다. 일부 UIViewController에서 UIButton 위에 UIWebView가 있습니다.

따라서 UIImage, 텍스트 등 UIWebView (일부) UIButton

위의 모든 것은 UIScrollView입니다.

2) UIWebView가있는 사람들의 경우 autoresizingMask는 다음과 같습니다.


   |

   ^
   |
   |

| — | ← ---- → | — | | | V UIButton의 마스크는 아무것도 설정되어 있지 않습니다.

내 -viewDidLoad 내에서 -repositionSubViews를 호출하여 다음을 수행합니다.

UIWebView가 없으면 IB로 배치 한 UIButton을 중앙에 두는 것 외에는 아무것도하지 않습니다.

UIWebView가 있으면 * content * Height를 결정하고 전체 내용을 포함하도록 프레임을 설정합니다.

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

일단 그렇게하면 프로그래밍 방식으로 UIButton을 아래로 밀어 UIWebView 아래에 배치됩니다.

세로에서 가로로 회전 할 때까지 모든 것이 작동합니다.

내 -didRotateFromInterfaceOrientation 내에서 -repositionSubViews를 호출합니다.

UIWebView의 컨텐츠 높이가 회전과 함께 변경되지 않는 이유는 무엇입니까?

세로에서 가로로 콘텐츠 너비가 확장되고 콘텐츠 높이가 줄어 듭니다. NSLog에 따르면 시각적으로 정상적으로 수행됩니다.

Anyway, with or without a UIWebView, the button I've talked about moves below the TabBar when in Landscape mode but it will not scroll up to be seen. I see it behind the TabBar when I scroll "vigorously", but then it "falls back" behind the TabBar.

Bottom line, this last is the reason I've asked about the height of the TabBar and the NavigationBar because the TabBar plants itself at the bottom of the UIView and the NavigationBar pushes the UIView down.

Now, I'm going to add a comment or two here because they wouldn't have made sense earlier.

With no UIWebView, I leave everything as is as seen by IB.

With a UIWebView, I increase the UIWebView's frame.height to its contentHeight and also adjust upward the height of the surrounding UIScrollView that surrounds all the sub-views.

Well there you have it.


Do something like this ?

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

The swift version is located here


UPDATE

iOS 13

As the statusBarFrame was deprecated in iOS13 you can use this:

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

With iPhone-X, height of top bar (navigation bar + status bar) is changed (increased).

Try this if you want exact height of top bar (both navigation bar + status bar):

Objective-C

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

Swift 4

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

For ease, try this UIViewController extension

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

Swift 3

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

UPDATE

iOS 13

As the statusBarFrame was deprecated in iOS13 you can use this:

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

Swift version:

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

Did you try this?

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

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 );
*/

So all we actually need is

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;

My application has a couple views that required a customized navigation bar in the UI for look & feel, however without navigation controller. And the application is required to support iOS version prior to iOS 11, so the handy safe area layout guide could not be used, and I have to adjust the position and height of navigation bar programmatically.

I attached the Navigation Bar to its superview directly, skipping the safe area layout guide as mentioned above. And the status bar height could be retrieved from UIApplication easily, but the default navigation bar height is really a pain-ass...

It struck me for almost half a night, with a number of searching and testing, until I finally got the hint from another post (not working to me though), that you could actually get the height from UIView.sizeThatFits(), like this:

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

    [super viewWillLayoutSubviews];    
}

Finally, a perfect navigation bar looking exactly the same as the built-in one!


The light bulb started to come on. Unfortunately, I have not discovered a uniform way to correct the problem, as described below.

I believe that my whole problem centers on my autoresizingMasks. And the reason I have concluded that is the same symptoms exist, with or without a UIWebView. And that symptom is that everything is peachy for Portrait. For Landscape, the bottom-most UIButton pops down behind the TabBar.

For example, on one UIView, I have, from top to bottom:

UIView – both springs set (default case) and no struts

UIScrollView - If I set the two springs, and clear everything else (like the UIView), then the UIButton intrudes on the object immediately above it. If I clear everything, then UIButton is OK, but the stuff at the very top hides behind the StatusBar Setting only the top strut, the UIButton pops down behind the Tab Bar.

UILabel and UIImage next vertically – top strut set, flexible everywhere else

Just to complete the picture for the few that have a UIWebView:

UIWebView - Struts: top, left, right Springs: both

UIButton – nothing set, i.e., flexible everywhere

Although my light bulb is dim, there appears to be hope.


Here is the beginning of my response to your update:

Why does the content height of my UIWebView not change with rotation?.

Could it be that because your auto resize doesn't have the autoresizingMask for all directions?

Another suggestion before I come back for this, could you use a toolbar for your needs. It's a little simpler, will always be on the bottom, auto-rotates/positions. You can hide/show it at will etc. Kind of like this: http://cdn.artoftheiphone.com/wp-content/uploads/2009/01/yellow-pages-iphone-app-2.jpg

You may have looked at that option, but just throwing it out there.

Another idea, could you possibly detect what orientation you are rotating from, and just place the button programmatically to adjust for the tab bar. (This is possible with code)


I have used:

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

Working great if you want to get the navigation bar height AND its Y origin.


Handy Swift 4 extension, in case it's helpful to someone else.

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

Usage:

UINavigationController.navBarHeight()

참고URL : https://stackoverflow.com/questions/7312059/programmatically-get-height-of-navigation-bar

반응형