1

所以,我试图在 Application UIWindow 上实现一个固定的顶部横幅和多个视图控制器的工作导航。我知道还有其他方法可以执行此操作,但对于我的项目要求,我需要使用 xibs。

下面的代码允许实现这一点:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    self.headerView = [[UIImageView alloc] init];
    self.headerView.frame = CGRectMake(0.0f, 20.0f, 320.0f, 44.0f);
    self.headerView.image = [UIImage imageNamed: @"header-banner-background.png"];
    [self.window addSubview:self.headerView];

    self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];

    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];

    self.window.rootViewController = navigationController;
    [self.window makeKeyAndVisible];
    return YES;
}

然后在每个 ViewController viewWillAppear 方法中,我调整了 self.view 和 self.navigationController.navigationBar.frame 的大小,以便在横幅下方显示自己:

self.navigationController.navigationBar.frame = CGRectMake(0, 64, 320, 44);
self.view.frame = CGRectMake(0, 64, 320, 396); 

这很好,完全按照我想要的方式工作。

但是如果用户按下主页按钮并且应用程序退出活动状态,当它再次变为活动状态时,最后一个 viewController 会显示但没有 UIWindow 横幅,并且 self.view 和 navigationBar 显示在顶部。

当然,当前的 UIViewController viewWillAppear 方法在应用程序返回活动时不会被调用,但即使我将调整大小代码放在另一个函数中并通过通知调用它也不起作用。但是当用户按下一个 bar item 并在导航堆栈中移动时,一切都会再次运行,UIWindow 会显示 headerView。

任何人都明白为什么当应用程序返回活动时 UIWindow headerView 会消失?

编辑1:可能的解决方案?

@interface RootViewController ()
{
    ViewController *viewController;
    UINavigationController *navigationController;
}

@end

@implementation RootViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
        viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
        navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
    }
    return self;
}

- (void)loadView
{
    // Implement loadView to create a view hierarchy programmatically, without using a nib.
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 88)];

    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    [imageView setImage:[UIImage imageNamed:@"header"]];

    [view addSubview:imageView];

    navigationController.navigationBar.frame = CGRectMake(0, 44, 320, 44); 

    [view addSubview:navigationController.navigationBar];

    self.view = view;

}

编辑 2:第二种可能的解决方案,仍然无法正常工作

- (void)loadView
{
    NSLog(@"loadView root");

    // Implement loadView to create a view hierarchy programmatically, without using a nib.
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 88)];

    UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    [imageView setImage:[UIImage imageNamed:@"banner"]];
    [view addSubview:imageView];

    navigationController = [[UINavigationController alloc] init];
    navigationController.navigationBar.frame = CGRectMake(0, 43, 320, 44); 
    [view addSubview:navigationController.navigationBar];

    [self addChildViewController:navigationController];

    self.view = view;
    [self.view setBackgroundColor:[UIColor yellowColor]];
}

这是结果,看起来很好,没有 viewController1 的推送(注意黄色背景来自 rootViewController):

无推

相反,这是添加的结果:

- (void)viewDidLoad
{
    viewController1 = [[ViewController1 alloc] initWithNibName:@"ViewController1" bundle:nil];
    [navigationController pushViewController:viewController1 animated:YES];    
}

带推

新的视图控制器没有被推送(背景应该是黑色的)并且导航栏已经消失了。

编辑 3:Olloqui 解决方案,仍然无法正常工作

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [self.window setBackgroundColor:[UIColor redColor]];

  UIView *bannerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    [self.window addSubview:bannerView];

    UIView *navigationView = [[UIView alloc] initWithFrame:CGRectMake(0, 44, 320, 416)];

    ViewController1 *viewController1 = [[ViewController1 alloc] initWithNibName:@"ViewController1" bundle:nil];
    self.navigationController = [[UINavigationController alloc] initWithRootViewController:viewController1];
    self.navigationController.navigationBar.frame = CGRectMake(0, 0, 320, 44); 

    [navigationView addSubview:self.navigationController.navigationBar];

    [self.window addSubview:navigationView];

    self.window.rootViewController = self.navigationController;

    self.window.autoresizesSubviews = YES;

    [self.window makeKeyAndVisible];
    return YES;
}

结果是我只有横幅,viewController1 被推送但没有显示导航栏。我真的需要弄清楚这一点,有人有不同的方法吗?

4

4 回答 4

1

窗口期望有一个由它的 rootViewController 属性控制的根视图。从后台返回时,窗口只要求 rootViewController 恢复该视图控制器视图的外观。它不会要求所有子视图刷新。

为了解决这个问题,我将创建一个新的根视图控制器。这将具有横幅和导航控制器。然后,该导航控制器将保存您的普通视图控制器并管理导航。应用程序从后台返回后,横幅将正确显示。当导航发生在导航控制器中时,您的横幅将是静止的。

编辑:我制作了一个小示例程序。

我从一个简单的单视图应用程序模板开始。我为内容添加了两个视图控制器。仅具有用于区分的标签,并且具有用于加载第二个视图的按钮。

所有的魔法都发生在主视图控制器的 viewDidLoad 方法中:

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
    OneViewController *oneVC = [[OneViewController alloc] initWithNibName:@"OneViewController" bundle:nil];
    self.navController = [[UINavigationController alloc]initWithRootViewController:oneVC];
    self.navController.view.frame = CGRectMake(0.0, 64.0, 320.0, 416.0);
    [self.view addSubview:self.navController.view];
    [self addChildViewController:self.navController];   
}

此视图的 nib 加载横幅的图像视图。

Bitbucket 上的示例项目。

于 2012-05-03T15:51:36.537 回答
1

我以前从未尝试过,但我会尝试在 UIWindow 中创建 2 个视图,一个用于横幅,另一个用于导航 + 内容。然后,在第二个视图中插入导航栏视图,该视图的大小将正确。我不确定导航是否会尝试占用整个窗口,但是在每个 viewWillAppear 上调整导航控制器的大小对我来说并不是一个好的解决方案。尝试并评论结果!

于 2012-05-03T15:51:47.077 回答
1

我认为您可以尝试通过将横幅视图添加到 window.rootViewController.view 来解决此问题,如下所示:

[window.rootViewController.view addSubview:bannerView]
于 2013-12-26T07:26:26.743 回答
0

好的,我真的需要尽快解决这个问题,因此我选择了一个我有幸在这里找到的解决方案。我仍然必须解决底部添加的 UITabBarController 的管理,但其余部分似乎工作正常。感谢大家的帮助和其他提示。

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

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    [self.window setBackgroundColor:[UIColor redColor]];

    // Create a view  for the banner add the banner to this view
    UIImageView *bannerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 45)];
    bannerImageView.image = [UIImage imageNamed:@"banner"];

    // put this banner above the nav bar 
    UIView *bannerView = [[UIView alloc] initWithFrame:CGRectMake(0, -44, 320, 44)];
    [bannerView addSubview:bannerImageView];

    //add the tabBarController as a subview of the view
    UITabBarController *tabBarController = [[UITabBarController alloc] init];
    [tabBarController.view addSubview:bannerView];

    // Move the root view to show status bar & banner
    tabBarController.view.frame = CGRectMake(0, 20+44, 320, 480-20-44); 

    //add the modified logo view to window
    [self.window addSubview:tabBarController.view];

    ViewController1 *viewController1 = [[ViewController1 alloc] initWithNibName:@"ViewController1" bundle:nil];
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController1];

    tabBarController.viewControllers = [NSArray arrayWithObjects:navigationController, nil];
    //tabBarController.tabBar.hidden = YES;

    [self.window setRootViewController:tabBarController];

    [self.window makeKeyAndVisible];
    return YES;
}
于 2012-05-04T12:31:53.690 回答