iOS 7 状态栏如何变成 iOS 6 的样式?

11

我有一个支持横屏和竖屏模式的应用程序。我需要与iOS 6上相同的状态栏行为。最简单的方法是什么?

我已经尝试了Stack Overflow问题“iOS 7状态栏回到iOS 6样式?”中的解决方案,但没有效果。我的子视图依赖于视图大小,我的视图无法正确地拉伸。我不想更新我的XIB文件; 我只想添加一些帮助我的东西。我不知道它可能是什么(黑客或祈祷)。


3
不明白为什么这个问题被关闭。很明显,在iOS编程中,状态栏样式是一个重要的知识点,这个问题可以帮助许多iOS程序员。采用iOS7不仅仅是更改一个png图片。 - Jay Zhao
我建议您需要设置navigationController.navigationBar.translucent = NO; 您遇到了什么问题? - Gralex
2
哦天啊,不要这样做。Swizzling 一个方法,而其他部分的代码将使用它,加上苹果的框架将会是灾难的配方... - Javier Soto
我同意你的观点。使用这种方法是很危险的。 - Gralex
@Sk0prion,您能否将解决方案添加为答案? - sathiamoorthy
显示剩余4条评论
5个回答

3

您可以尝试在ViewWillAppear或DidAppear中编写此代码。这里我们将视图框架下移20像素。

CGRect frame = self.view.frame;
frame.origin.y = 20;

if (self.view.frame.size.height == 1024 || 
    self.view.frame.size.height == 768)
{
    frame.size.height -= 20;
}

self.view.frame = frame;

这种方法可以实现,但并不是一个很好的想法。如果有需要,您也可以通过调用以下方法将状态栏文本颜色更改为浅色或深色,以适应您的应用程序背景。

-(UIStatusBarStyle)preferredStatusBarStyle
{
     return UIStatusBarStyleLightContent; // For light status bar

     return UIStatusBarStyleDefault // For Dark status bar
}

我想把一些代码放在一个地方,而不是在整个应用程序中到处都是。UIViewController上的交换方法是不好的解决方案:因为我可以 [viewController1.view addSubview:viewController2.view] - Gralex
尝试将上述代码放置在您的viewController1的DidAppear方法中。如果您希望您的应用程序看起来像iOS 6,那么几乎没有其他方法。另一个选择是将所有子视图向下移动20像素,但这需要大量工作。 - Bhumit Mehta
谢谢,如果我找不到简单的解决方案,我会使用你的解决方案。但我不想这样做,因为我的应用程序有很多视图。 - Gralex

2
如果您使用的是Xcode 5,且正在安装iOS 7,则很抱歉,这是不可能的(据我所知)。
如果您想在iOS 7上看到像iOS 6一样的状态栏,请在Xcode 4.x.x中打开您的项目并在iOS 7中进行安装。我发现这种方法的一个问题是,有时Xcode 4.x.x无法识别iOS 7设备。
但是,如果您的Xcode 4.x.x可以显示您的iOS 7设备,则它将起作用。
从Xcode 4.x.x生成的.api将在iOS 6和iOS 7中均可使用,但您将无法在iOS 7上获得额外的状态栏空间以及键盘、选择器、开关等的新外观。但是,您将获得新的UIAlertView(我不知道为什么这是新的,而其他控件却是旧的)。
我希望我们很快能在Xcode 5中找到更好的解决方案。
更新:
我找到了一种以Xcode 4的方式从Xcode 5运行应用程序的方法。这只是基础SDK的问题。 如果您想从Xcode 5构建为Xcode 4(iOS 6 SDK),请执行以下操作。
1.关闭Xcode 4和5。 2.在Xcode 4中转到 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs 3.在这里,您将找到iPhoneOS6.1.sdk。复制此文件夹。现在在相同的路径下进入Xcode 5。在Xcode 5中,您将找到iPhoneOS7.0.sdk。将iPhoneOS6.1.sdk与其粘贴。 4.现在关闭Finder并启动Xcode 5。转到项目目标设置 - >构建设置并查找基本SDK。选择iOS 6.1作为基本SDK。这也适用于6.0。您只需要找到iPhoneOS6.0.sdk。 5.现在您将在运行下拉框中看到设备名称两次。一个用于SDK 7.0,另一个用于SDK 6.1。因此,现在您可以以iOS 6 SDK和iOS 7 SDK两种方式运行。
我希望这会对某些人有所帮助。

我想在App Store上上传我的应用程序。据我所知,我无法使用xCode 4.6.x完成此操作。 - Gralex
我已经尝试了许多在线解决方案,但都没有对我起作用。您可以从Xcode 4.6.x上传。我已经从Xcode 4.6.x上传了两个应用程序,并且运行良好。您需要的额外内容是iOS 7大小的图标。 - CRDave
我渴望知道那个。 - CRDave
我找到了这个解决方案https://dev59.com/fGMl5IYBdhLWcg3wknsT#18966372。 - İbrahim Özbölük
这是不正确的。你可以在Xcode 5中将其视为iOS 6,在Interface Builder的Storyboard设置中选择它。永远不要使用旧版本的Xcode。 - Raptor
@Raptor 是的,你可以在界面构建器中看到这一点,我非常清楚。但是,如果你在运行 iOS 7 的设备上,你将不会在那里看到状态栏,因为 Xcode 使用 iOS SDK 7 来构建应用程序,即使你在 storyboard 中选择了 iOS 6 视图。 - CRDave

0

最近我也遇到了类似的问题,但是我采用了略微不同的方法来解决它...

我的方法是使用一个额外的视图控制器作为原本根视图控制器的容器视图控制器。首先,我像这样设置了一个容器:

_containerView = [[UIView alloc] initWithFrame:[self containerFrame]];
_containerView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
_containerView.clipsToBounds = YES;

[self.view addSubview:_containerView];
[self.view setBackgroundColor:[UIColor blackColor]];

[UIApplication.sharedApplication setStatusBarStyle:UIStatusBarStyleLightContent animated:NO];

containerFrame 的定义如下:

- (CGRect)containerFrame
{
    if ([MyUtilityClass isSevenOrHigher])
    {
        CGFloat statusBarHeight = [MyUtility statusBarHeight]; //20.0f
        return CGRectMake(0, statusBarHeight, self.view.bounds.size.width, self.view.bounds.size.height - statusBarHeight);
    }

    return self.view.bounds;
}

最后,我将原本的rootViewController作为新视图控制器的childViewController添加进去:
//Add the ChildViewController
self.childController.view.frame = self.containerView.bounds;
self.childController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self addChildViewController:self.childController];
[self.containerView addSubview:self.childController.view];
[self.childController didMoveToParentViewController:self];

需要注意的事项: - Modal视图控制器仍将以iOS7样式呈现,因此我仍然必须对此进行考虑。

希望这能帮助到某些人!


0

这个指南对我很有帮助。

http://www.doubleencore.com/2013/09/developers-guide-to-the-ios-7-status-bar/

处理 20 点大小差异最健壮的方法是使用自动布局。
如果您没有使用自动布局,界面生成器会提供工具来处理 iOS 7 和旧版本之间的屏幕大小差异。当关闭自动布局时,您会注意到界面生成器实用程序区域(右窗格)调整选项卡中有一个区域,允许您设置 iOS 6/7 Delta。

-1

1) 这是一个hack,但它有效!

如果您不使用UIAlertView或KGStatusBar,请使用它!

#import <objc/runtime.h>

@interface UIScreen (I_love_ios_7)
- (CGRect)bounds2;
- (CGRect)boundsForOrientation:(UIInterfaceOrientation)orientation;
@end

@implementation UIScreen (I_love_ios_7)
- (CGRect)bounds2
{
    return [self boundsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
}

- (CGRect)boundsForOrientation:(UIInterfaceOrientation)orientation
{
    CGRect resultFrame = [self bounds2];
    if(UIInterfaceOrientationIsLandscape(orientation))
        resultFrame.size.width -= 20;
    else
        resultFrame.size.height -= 20;
    return resultFrame;
}
@end

void Swizzle(Class c, SEL orig, SEL new)
{
    Method origMethod = class_getInstanceMethod(c, orig);
    Method newMethod = class_getInstanceMethod(c, new);
    if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
        class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
    else
        method_exchangeImplementations(origMethod, newMethod);
}


@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
        Swizzle([UIScreen class], @selector(bounds2), @selector(bounds));
        [application setStatusBarStyle:UIStatusBarStyleLightContent];
        self.window.clipsToBounds =YES;

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(applicationDidChangeStatusBarOrientation:)
                                                     name:UIApplicationWillChangeStatusBarOrientationNotification
                                                   object:nil];
        NSDictionary* userInfo = @{UIApplicationStatusBarOrientationUserInfoKey : @([[UIApplication sharedApplication] statusBarOrientation])};
        [[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationWillChangeStatusBarOrientationNotification
                                                            object:nil
                                                          userInfo:userInfo];
    }

    return YES;
}

- (void)applicationDidChangeStatusBarOrientation:(NSNotification *)notification
{
    UIInterfaceOrientation orientation = [[notification.userInfo objectForKey: UIApplicationStatusBarOrientationUserInfoKey] intValue];
    CGSize size = [[UIScreen mainScreen] boundsForOrientation:orientation].size;
    int w = size.width;
    int h = size.height;
    float statusHeight = 20.0;
    switch(orientation){
        case UIInterfaceOrientationPortrait:
            self.window.frame =  CGRectMake(0,statusHeight,w,h);
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            self.window.frame =  CGRectMake(0,0,w,h);
            break;
        case UIInterfaceOrientationLandscapeLeft:
            self.window.frame =  CGRectMake(statusHeight,0,w,h);
            break;
        case UIInterfaceOrientationLandscapeRight:
            self.window.frame =  CGRectMake(0,0,w,h);
            break;
    }
}
@end

2) 创建类别,并始终使用 contentView 而不是 view

@interface UIViewController(iOS7_Fix)
@property (nonatomic, readonly) UIView* contentView;
- (void)updateViewIfIOS_7;
@end

@implementation UIViewController(iOS7_Fix)
static char defaultHashKey;
- (UIView *)contentView
{
    return objc_getAssociatedObject(self, &defaultHashKey)?: self.view;
}

- (void)setContentView:(UIView *)val
{
    objc_setAssociatedObject(self, &defaultHashKey, val, OBJC_ASSOCIATION_RETAIN_NONATOMIC) ;
}

- (void)updateViewIfIOS_7
{
    if([[[UIDevice currentDevice] systemVersion] floatValue] < 7 || objc_getAssociatedObject(self, &defaultHashKey))
        return;

    UIView* exchangeView = [[UIView alloc] initWithFrame:self.view.bounds];
    exchangeView.autoresizingMask = self.view.autoresizingMask;
    exchangeView.backgroundColor = [UIColor blackColor];

    UIView* view = self.view;
    if(self.view.superview){
        [view.superview addSubview:exchangeView];
        [view removeFromSuperview];
    }
    [exchangeView addSubview:view];
    self.view = exchangeView;

    CGRect frame = self.view.bounds;
    frame.origin.y += 20.0;
    frame.size.height -= 20.0;
    view.frame = frame;
    view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    [self setContentView:view];
}

在每个UIViewController中:
- (void)viewDidLoad
{
    [super viewDidLoad];
    [self updateViewIfIOS_7];
    UILabel* lab = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 130, 30)];
    lab.backgroundColor = [UIColor yellowColor];
    [self.contentView addSubview:lab];
    //...
}

Portrait Landscape


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接