3

and thanks in advance.

I am looking for advice on how to layout the view controllers in my app, where I still have a persistent background along with a few background animations

This is how it is set up currently:

  • AppDelegate makes a navigations controller, RootViewController and a Sprite Layer (which subclasses UIView)
  • AppDelegate also holds the background image as its backgroundColor property
  • the navigation controller is initialized with the root view controller, as normal
  • the rootview controller pushes different table views onto the navigation stack

And in code:

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

UIImageView* backgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"underthesea.jpg"]] autorelease];
backgroundView.contentMode = UIViewContentModeScaleAspectFill;
backgroundView.frame = [UIScreen mainScreen].bounds;

self.viewController = [[[RootViewController alloc] init] autorelease];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.spriteLayer = [[[SpriteLayer alloc] initWithFrame:self.viewController.view.frame] autorelease];
self.viewController.spriteLayer = self.spriteLayer;

[window addSubview:backgroundView];    
[window addSubview:self.spriteLayer];
[window addSubview:self.navigationController.view];

[window makeKeyAndVisible];
return YES;
}

`

All the time, the Sprite Layer is visible in the background, containing different animations. The problem is that now I am trying to implement autorisizing and having difficulties because the views in the sprite layer are not within a UIViewController.

I think one possibility is to make the SpriteLayer subclass UIViewController, but don't put it in the navigation controller; it would just exist behind whatever view the navigation controller is displaying. I don't know if having 2 view controllers at the same time like this will be a source of bugs or just bad design, as I have read on StackOverflow that this is not the intended design of view controllers.

Any opinions here?

Cheers, Rich

P.S. I am having trouble putting an objective C method within a code block. The back tick doesn't seem to work, as the only part of the code that ends up in the code font is that which is indented. Anyone know the correct way to do this? Thanks again.

rich.e
  • 3,660
  • 4
  • 28
  • 44

2 Answers2

5

Bentford, I didn't think to add the SpriteLayer view directly to the UINavigation view, as I didn't think this was the intended use of UINavigation. But it works like a charm :)

All I had to change was:

[window addSubview:backgroundView];    
[window addSubview:self.spriteLayer];
[window addSubview:self.navigationController.view];

to:

[self.navigationController.view insertSubview:backgroundView atIndex:0];
[self.navigationController.view insertSubview:self.spriteLayer atIndex:1];
[window addSubview:self.navigationController.view];

and then add a little autoresizeMask to the backgroundView and poof I have an autoresizing background + sprites that doesn't git swiped out when a view controller is pushed onto the navigation stack.

Thanks for your suggestions!

rich.e
  • 3,660
  • 4
  • 28
  • 44
  • In my current implementation, the background image and SpriteLayer are members of RootViewController, and I add them to the navigation controller's view in the RootViewController's loadView. Then, I can use the autoresizing hooks built into UIViewControllers. – rich.e Nov 14 '10 at 16:32
0

Don't use multiple view controllers. Instead, have SpriteLayer subclass UIView and add it directly to your currently visible UIViewController's view.

Remember only the visible UIViewController will fire rotation events. But with SpriteLayer setup this way, you can use autoresizing or manually resize it in didRotateToInterfaceOrientation.

SpriteLayer can be added to your UINavigationController by simply adding it to the view property. A good way to do this is by subclassing UINavigationController and override viewDidLoad:

- (void)viewDidLoad {
    [super viewDidLoad];

    SpriteLayer *spriteLayer = [[SpriteLayer alloc] initWithFrame:CGRectMake(0, 300, 320, 50)];
    [self.view addSubview:spriteLayer];

}

The pushing and popping animation will run behind the SpriteLayer. Other behaviors can be achieved by using sendSubviewToBack and related UIView methods.

bentford
  • 33,038
  • 7
  • 61
  • 57
  • The problem with adding SpriteLayer to the current UIViewController is that it will cause all of the contents in SpriteLayer to slide in from the side, as part of the desired animation for that UIViewController. What I would like is for the SpriteLayer to lay underneath the animation of the view controller (this is why I added it to the main window in AppDelegate) – rich.e Nov 14 '10 at 09:05
  • I had alot of problems subclassing UINavigationController, as I really couldn't gain any functionality or control of the resizing. – rich.e Nov 14 '10 at 16:30
  • Subclassing UINavigationController is not necessary. I have a working example of this I can post. Still interested? – bentford Dec 01 '10 at 16:33