2014-09-07 2 views
1

상태 표시 줄 자체를 제거하지 않고 상태 표시 줄 텍스트를 숨기고 싶습니다.상태 표시 줄 자체를 제거하지 않고 상태 표시 줄 텍스트 페이드

전 화면에 새로운보기 컨트롤러를 제공하고 있으며보기 컨트롤러가 전체 화면을 가져 왔을 때 상태 표시 줄 텍스트가 표시되지 않게하려고합니다. 제시된 뷰 컨트롤러는 UINavigationBar이지만 제시된 뷰 컨트롤러는 그렇지 않습니다.

나는 prefersStatusBarHiddentrue을 단순히 반환하려고했으나 상태 표시 줄 프레임이 제거되어 제시 컨트롤러의 탐색 컨트롤러가 위로 올라가고 새보기 컨트롤러가 여전히 위로 움직이는 동안 표시됩니다 바닥.

는 그때 그때 viewDidAppear에서 setNeedsStatusBarAppearanceUpdate()를 호출 preferredStatusBarUpdateAnimationprefersStatusBarHidden.Fadefalse를 반환하지만,이 흰색에서 검은 색과 눈에 보이는 나머지로 변경 상태 표시 줄 텍스트 결과, 제시된보기 컨트롤러 truemodalPresentationCapturesStatusBarAppearance을 설정했습니다. prefersStatusBarHiddentrue으로 설정하면 앞에서 설명한 것처럼 상태 표시 줄이 제거됩니다.

이상적으로, 나는 segue를 시작할 때 상태 표시 줄의 텍스트가 희미 해지기 시작하고 애니메이션이 완료되면 알파가 0이됩니다. 그런 다음 해고가 끝나면 알파 1로 되돌아갑니다.이 또는 유사한 솔루션이 가능합니까? iOS 8 이상 만 지원하면됩니다.

+0

"제시하는 뷰 컨트롤러에는 UINavigationBar가 있지만 표시 컨트롤러에는 표시되지 않습니다." 그것이 모순이라는 것을 알고 있습니까? 제목에서 보면,이 말은 정말 간단한 질문처럼 들리지만, 당신의 말씨는 이것을 정말로 어렵게 만들었습니다. 작성한 내용을 검토하십시오. – michaelsnowden

+0

@doctordoder 두 번째 것이 "제시된"것이어야합니다 - fixed – Joey

+0

View Controller를 제시 할 때 상태 표시 줄이 숨겨져 있기 때문에 제시된보기 컨트롤러의 탐색 막대가 위로 올라 오지 않으려 고합니다. (제시된 뷰 컨트롤러가 상태 표시 줄을 가져서는 안되는 것처럼 들리지만 상태 표시 줄을 유지하면서 현재/해제 애니메이션을 위해 보이지 않게하려고합니다.) – user2135004

답변

1

사실, 상태 표시 줄을 사용하여 창에 직접 액세스하고 원하는대로 할 수 있습니다.

- (UIWindow *)statusBarWindow 
{ 
    return (UIWindow *)[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"]; 
} 

물론 문서화되지 않은 기능이며 앱 리뷰 프로세스 측면에서 위험 할 수 있지만 그와 관련된 긍정적 인 경험이 있습니다.

1

해결책 1 : 내가 가진 해결책은 매우 해킹되지만 작동합니다. 먼저 제공된 뷰 컨트롤러는 modalPresentationCapturesStatusBarAppearanceYES으로 설정하고 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이라고 부릅시다. 이 클래스를 UINavigationControllerinitWithNavigationBarClass: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:에서 수행하고 실제로이 방법으로 애니메이션을 수행하기 전에 수행하십시오.

+0

실제로 그것은 꽤 hackish입니다. 개인적으로 나는 마술 코드를 구현하는 것보다 오히려 슬라이딩 상태 표시 줄을 다루 겠지만 좋았습니다. :) 다른 솔루션이 있는지 궁금해합니다.보기 컨트롤러를 강화하는 방법은 상태 표시 줄의 겹쳐 보이기 때문에 항상 표시 할 수 있습니다. 상태 표시 줄을 제거하지 않고 알파를 변경하는 방법은 무엇입니까? – Joey

+0

@Joey 시도해 볼 또 다른 아이디어는 프리젠 테이션/해산 애니메이션 중에 프리젠 테이션 뷰 컨트롤러의 스냅 샷을 스탠드 인으로 가져 오는 것입니다. 그런 식으로 바가 위아래로 움직이는 것에 대해 걱정할 필요가 없습니다. – user2135004