Ios 淡入状态栏文本而不删除状态栏本身
我想隐藏状态栏文本而不删除状态栏本身Ios 淡入状态栏文本而不删除状态栏本身,ios,swift,statusbar,alpha,Ios,Swift,Statusbar,Alpha,我想隐藏状态栏文本而不删除状态栏本身 我正在全屏显示一个新的视图控制器,我不希望状态栏文本在视图控制器接管全屏时可见。请注意,呈现视图控制器有一个UINavigationBar,而呈现视图控制器没有 我曾尝试在prefersStatusBarHidden中简单地返回true,但这会导致状态栏框架被删除,导致演示视图控制器上的导航控制器向上滑动,并且在新视图控制器仍从底部向上动画时,这是可见的 然后,我尝试将显示的视图控制器的modalPresentationCapturesStatusBarAp
我正在全屏显示一个新的视图控制器,我不希望状态栏文本在视图控制器接管全屏时可见。请注意,呈现视图控制器有一个
UINavigationBar
,而呈现视图控制器没有
我曾尝试在prefersStatusBarHidden
中简单地返回true
,但这会导致状态栏框架被删除,导致演示视图控制器上的导航控制器向上滑动,并且在新视图控制器仍从底部向上动画时,这是可见的
然后,我尝试将显示的视图控制器的modalPresentationCapturesStatusBarAppearance
设置为true
,然后在PreferenceStatusBarHidden
中返回false
,在preferredStatusBarUpdateAnimation
中调用SetNeedssStatusBarAppearanceUpdate()
在视图中出现
,但这会导致状态栏文本从白色变为黑色并保持可见。将prefersStatusBarHidden
设置为true
将删除我前面提到的状态栏
理想情况下,我会在启动segue时开始淡入状态栏上的文本,动画完成时alpha将达到0。然后在被解雇后,回到阿尔法1。这是可能的还是类似的解决方案?我只需要支持iOS 8+。解决方案1:我的解决方案非常粗糙,但很有效。首先,显示的视图控制器应将
modalPresentationCapturesStatusBarAppearance
设置为YES
,并应返回YES
作为首选状态BarHidden
现在,问题是导航栏不能向上滑动。为此,首先子类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
可能会考虑到状态栏实际上已被隐藏,即使我们总是强制为假想的状态栏留出空间
要解决第一个问题,首先将ForcedNavigationBar
的backgroundColor
属性设置为[UIColor clearColor]
并覆盖drawRect:
使其背景不可见(不调用super
)。(导航栏的按钮仍然可见。)现在,我们在真实导航栏下放置一个虚拟导航栏,以提供一个背景,该背景将始终位于虚拟状态栏空间的下方。我们可以通过子类化UINavigationController
(称之为ForcedNavigationBar
)并向虚拟导航栏添加约束来实现这一点:
- (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];
}
}
要解决第二个问题,只需不使用topLayoutGuide
,而是根据导航栏的位置设置顶部的空间。对于不是滚动视图的视图,可以更新相对于viewWillLayoutSubviews
中导航栏定位这些视图的约束。如果您有一个滚动视图(如表格视图),则可以在viewdilayoutsubview
中调整其contentInset
的顶部。(以前,您应该将滚动视图的contentInset
顶部设置为topLayoutGuide.length
)
我提供的代码可以在iPhone5屏幕上运行。在iOS 8中,您必须使此代码“自适应”,这样它在iPhone 6屏幕上仍然可以工作。例如,在横向定位中,iPhone 6上的导航栏可能没有挤压
编辑:解决方案2:使用SnapshotViewAfterScreenuUpdate
拍摄演示视图控制器的快照视图,并在演示或取消之前将其插入视图层次结构中。这样,您就不必担心导航栏会上下滑动。(我个人还没有尝试过,但似乎很有希望。)
编辑2:此解决方案的一个小问题是,在取消之前,导航栏将没有空间放置状态栏。如果您使用
UIViewControllerAnimatedTransitioning
进行解雇,则使用空动画块调用[UIView animationionwithduration:…]
似乎(以某种方式)强制系统让“to”视图控制器(导航控制器)指定状态栏外观。然后,要使“to”视图控制器布局并为状态栏留出空间,可以在容器视图或其中包含“to”视图控制器的某个视图上调用layoutifneed
。在animateTransition:
中执行所有这些操作,但在使用此方法实际执行动画之前。实际上,您可以直接使用状态栏访问窗口,并对其执行任何操作
- (UIWindow *)statusBarWindow
{
return (UIWindow *)[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"];
}
当然,它是未记录的功能,在应用程序审查过程中可能会有危险,但我对此只有积极的经验。“请注意,演示视图控制器有一个UINavigationBar,而演示视图控制器没有。”您意识到这是一个矛盾吗