해결책 1 : 내가 가진 해결책은 매우 해킹되지만 작동합니다. 먼저 제공된 뷰 컨트롤러는 modalPresentationCapturesStatusBarAppearance
을 YES
으로 설정하고 prefersStatusBarHidden
에 대해 YES
을 반환해야합니다.
이제 문제는 탐색 모음이 위로 움직이지 않는 것입니다. 이렇게하려면 먼저 UINavigationBar
서브 클래스를 지정하고 setFrame:
, setBounds:
및 setCenter:
을 재정 의하여 상태 표시 줄이 숨겨져있을 때도 위로 이동하려는 경우에도 탐색 모음의 모양과 위치를 고정하십시오. 다음과 같이 입력하십시오 :
const CGFloat kStatusBarHeight = 20;
const CGFloat kDefaultNavigationBarHeight = 44;
const CGFloat kLandscapeNavigationBarHeight = 32;
...
- (void)setCenter:(CGPoint)center {
center = [self forcedCenterForCenter:center];
[super setCenter:center];
}
- (void)setBounds:(CGRect)bounds {
bounds = [self forcedBoundsForBounds:bounds];
[super setBounds:bounds];
}
- (void)setFrame:(CGRect)frame {
frame = [self forcedFrameForFrame:frame];
[super setFrame:frame];
}
- (CGPoint)forcedCenterForCenter:(CGPoint)center {
if (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation)) {
center.y = kStatusBarHeight + kDefaultNavigationBarHeight * 0.5;
}
else {
// No status bar in landscape orientation in iOS 8.
center.y = kLandscapeNavigationBarHeight * 0.5;
}
return center;
}
- (CGRect)forcedBoundsForBounds:(CGRect)bounds {
if (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation)) {
bounds.size.height = kDefaultNavigationBarHeight;
}
else {
bounds.size.height = kLandscapeNavigationBarHeight;
}
return bounds;
}
- (CGRect)forcedFrameForFrame:(CGRect)frame {
if (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation)) {
frame.origin.y = kStatusBarHeight;
frame.size.height = kDefaultNavigationBarHeight;
}
else {
// No status bar in landscape orientation in iOS 8.
frame.origin.y = 0.0;
frame.size.height = kLandscapeNavigationBarHeight;
}
return frame;
}
이 클래스를 ForcedNavigationBar
이라고 부릅시다. 이 클래스를 UINavigationController
의 initWithNavigationBarClass:toolbarClass:
에 전달하면 탐색 바가 그대로 유지되지만 다른 문제가 발생합니다. 첫째, 경우에 따라 탐색 모음이 위쪽으로 확장되어 상태 표시 줄을 언더 레이 랩핑하지 않습니다. 두 번째로, 내비게이션 컨트롤러에 밀어 넣은 뷰 컨트롤러는 topLayoutGuide
속성을 더 이상 사용하지 않아야합니다. 왜냐하면 topLayoutGuide
은 상상의 상태 표시 줄을위한 공간을 항상 강제하더라도 상태 표시 줄이 실제로 숨겨져 있기 때문입니다.
먼저, 첫 번째 문제를 해결 절대적으로 아무것도 (
super
없이 전화를) 할 수 없습니다
[UIColor clearColor]
및 최우선
drawRect:
에 그
backgroundColor
속성을 설정하여
ForcedNavigationBar
의 배경이 보이지 않게합니다. 탐색 바의 버튼은 여전히 표시됩니다. 이제 실제 탐색 바 아래에 더미 탐색 모음을 배치하여 상상의 상태 표시 줄에 대한 공간을 항상 밑돌고있는 배경을 제공합니다.방금
topLayoutGuide
를 사용하고 기반으로 상단에있는 공간을 설정할 필요가
- (void)viewDidLoad {
[super viewDidLoad];
UINavigationBar * backgroundNavigationBar = [[UINavigationBar alloc] init];
[self.navigationBar.superview insertSubview:backgroundNavigationBar belowSubview:self.navigationBar];
{
backgroundNavigationBar.translatesAutoresizingMaskIntoConstraints = NO;
// The background bar always hugs the top of the screen.
NSLayoutConstraint * topConstraint = [NSLayoutConstraint constraintWithItem:backgroundNavigationBar
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1
constant:0];
[self.view addConstraint:topConstraint];
NSLayoutConstraint * bottomConstraint = [NSLayoutConstraint constraintWithItem:backgroundNavigationBar
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.navigationBar
attribute:NSLayoutAttributeBottom
multiplier:1
constant:0];
[self.navigationBar.superview addConstraint:bottomConstraint];
NSLayoutConstraint * leftConstraint = [NSLayoutConstraint constraintWithItem:backgroundNavigationBar
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self.navigationBar
attribute:NSLayoutAttributeLeft
multiplier:1
constant:0];
[self.navigationBar.superview addConstraint:leftConstraint];
NSLayoutConstraint * rightConstraint = [NSLayoutConstraint constraintWithItem:backgroundNavigationBar
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:self.navigationBar
attribute:NSLayoutAttributeRight
multiplier:1
constant:0];
[self.navigationBar.superview addConstraint:rightConstraint];
}
}
는 두 번째 문제를 해결하기 위해 우리는 UINavigationController
을 (ForcedNavigationBar
를 호출) 서브 클래스와 더미 탐색 모음에 제약 조건을 추가하여이 작업을 수행 할 수 있습니다 네비게이션 바를 배치 할 곳을 지정하십시오. 스크롤 뷰가 아닌 뷰의 경우 탐색 모음을 기준으로 상대적 위치를 지정하는 제약 조건을 viewWillLayoutSubviews
으로 업데이트 할 수 있습니다. 스크롤 뷰 (예 : 테이블 뷰)가있는 경우 contentInset
의 윗부분을 viewDidLayoutSubviews
으로 조정할 수 있습니다. 이전에는 스크롤 뷰의 contentInset
의 윗부분을 topLayoutGuide.length
으로 설정했을 것입니다.
제공된 코드는 iPhone 5 화면에서 작동합니다. iOS 8에서는이 코드를 "적응 형"으로 설정해야하므로 iPhone 6 화면에서도 계속 작동합니다. 예를 들어, 아마 가로 방향으로 탐색 모음은 아이폰에 숙청되지 않고, 경우의 6
편집 : 해결 방법 2 : 사용 snapshotViewAfterScreenUpdates
내원 뷰 컨트롤러의 스냅 샷보기를 타고 삽입하기 프리젠 테이션 또는 해고 전에 뷰 계층 구조에서. 그렇게하면 탐색 막대가 위아래로 움직이는 것에 대해 걱정할 필요가 없습니다. (개인적으로 시도한 것은 아니지만 유망한 것으로 보입니다.)
EDIT 2 :이 솔루션에 약간의 주름은 탐색 모음에 해지 직전 상태 표시 줄을위한 공간이 없다는 것입니다. 해고에 UIViewControllerAnimatedTransitioning
을 사용하는 경우 빈 애니메이션 블록이있는 [UIView animationWithDuration:...]
을 호출하면 시스템에 "상태"보기 컨트롤러 (탐색 컨트롤러)가 상태 표시 줄의 모양을 나타낼 수 있습니다. 그런 다음 상태 표시 줄을위한 공간이있는 "to"뷰 컨트롤러를 배치하려면 콘테이너 뷰 또는 컨트롤러의 "to"뷰가있는 뷰에서 layoutIfNeeded
으로 호출하십시오. 이 모든 작업을 animateTransition:
에서 수행하고 실제로이 방법으로 애니메이션을 수행하기 전에 수행하십시오.
"제시하는 뷰 컨트롤러에는 UINavigationBar가 있지만 표시 컨트롤러에는 표시되지 않습니다." 그것이 모순이라는 것을 알고 있습니까? 제목에서 보면,이 말은 정말 간단한 질문처럼 들리지만, 당신의 말씨는 이것을 정말로 어렵게 만들었습니다. 작성한 내용을 검토하십시오. – michaelsnowden
@doctordoder 두 번째 것이 "제시된"것이어야합니다 - fixed – Joey
View Controller를 제시 할 때 상태 표시 줄이 숨겨져 있기 때문에 제시된보기 컨트롤러의 탐색 막대가 위로 올라 오지 않으려 고합니다. (제시된 뷰 컨트롤러가 상태 표시 줄을 가져서는 안되는 것처럼 들리지만 상태 표시 줄을 유지하면서 현재/해제 애니메이션을 위해 보이지 않게하려고합니다.) – user2135004