iOS: Add UIView below UINavigationBar - ios

if I try to add a view to the navigation bar in my custom UINavigationController with this code:
- (void)viewDidLoad {
[super viewDidLoad];
self.sv = (MyCustomView *)[[[NSBundle mainBundle]loadNibNamed:#"MyCustomView" owner:self options:nil] objectAtIndex:0];
self.sv.frame = CGRectMake(self.navigationBar.frame.origin.x, self.navigationBar.frame.size.height, self.navigationBar.frame.size.width, heightOfMyCustomView);
[self.navigationBar addSubview:self.sv];
}
and
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[super pushViewController:viewController animated:animated];
viewController.view.frame = CGRectMake(viewController.view.frame.origin.x, viewController.view.frame.origin.y + heightOfMyCustomView, viewController.view.frame.size.width, viewController.view.frame.size.height - heightOfMyCustomView);
}
when I push a controller, the top part of the controller's view is hidden by my custom view I added to the navigation bar.
How can I put the controller's view down below my custom view?

I'd also suggest to take a look at UINavigationItem.titleView property, that gives you an ability to provide your view for navigation bar title area.

In your custom UINavigationController init method assign delegate to itself, like this:
CustomeNavCtrl.m file:
#implementation CustomeNavCtrl
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.delegate = self;
}
return self;
}
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
//Todo:viewController.view layout
//Todo:send MyCustomView to back or something other you like.
}
CustomeNavCtrl.h file:
#interface CustomeNavCtrl : UINavigationController<UINavigationControllerDelegate> {
}

Related

How to restore subview of view controller using state restoration

I am using state restoration to restore previous views and data for my app.When a button is clicked in first view controller I am to pushing second view control.In this case I am able to restore second view controller data.But if I add second View Controller view as subview to first view controller when button is clicked in first view Controller, encodeRestorableStateWithCoder: and decodeRestorableStateWithCoder: were not called in second view controller.Unable to restore second view controller data.Do I need to do any other configurations to restore subview data ?
//Firstviewcontroller
-(IBAction)moveToNextViewController:(id)sender {
SecondVeiwController *sec_VC=[[SecondVeiwController alloc]initWithNibName:#"SecondVeiwController" bundle:[NSBundle mainBundle ]];
sec_VC.restorationIdentifier=#"SecondVeiwController";
[self.view addSubview:tab_cnt_1.view];
}
//Secondviewcontroller
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
self.restorationIdentifier=#"Secondviewcontroller";
self.restorationClass=[self class];
}
return self;
}
+(UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
{
UIViewController * myViewController =
[[Secondviewcontroller alloc]
initWithNibName:#"Secondviewcontroller"
bundle:[NSBundle mainBundle]];
return myViewController;
}
It seems that iOS does not keep track of subviews, you have to encode the SecondViewController and then decode and add it as a child view controller with its view as a subview.
//FirstViewController
-(void)encodeRestorableStateWithCoder:(NSCoder *)coder {
[super encodeRestorableStateWithCoder:coder];
[coder encodeObject:self.childViewControllers[0] forKey:#"childVC"];
}
-(void)decodeRestorableStateWithCoder:(NSCoder *)coder {
[super decodeRestorableStateWithCoder:coder];
UIViewController *v = [coder decodeObjectForKey:#"childVC"];
[self addChildViewController:v];
[self.view addSubview:v.view];
}
//SecondViewController
-(void)encodeRestorableStateWithCoder:(NSCoder *)coder {
[super encodeRestorableStateWithCoder:coder];
[coder encodeObject:self.view.backgroundColor forKey:#"bgColor"];
}
-(void)decodeRestorableStateWithCoder:(NSCoder *)coder {
[super decodeRestorableStateWithCoder:coder];
UIColor *bgColor = [coder decodeObjectForKey:#"bgColor"];
[self.view setBackgroundColor:bgColor];
}

how to show spine in uipageviewcontroller?

I am creating a simple UIPageViewController with just two pages, how do I show the spine? Currently there is nothing in the middle. Also the outside borders are missing.
This is the code for UIPageViewController
//
// PageViewController.m
// pageuiviewproject
//
//
#import "PageViewController.h"
#import "contentViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface PageViewController ()
#property (nonatomic, strong) UIPageViewController *pageViewController;
#end
#implementation PageViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageViewController.delegate = self;
self.pageViewController.dataSource = self;
NSArray *viewControllers = [NSArray arrayWithObject:[[contentViewController alloc]init]];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
self.pageViewController.view.layer.borderColor = [UIColor blackColor].CGColor;
self.pageViewController.view.layer.borderWidth = 3.0f;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UIPageViewController delegate methods
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController{
return [[contentViewController alloc] init];
}
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController{
return [[contentViewController alloc] init];
}
-(UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation{
NSArray *viewControllers = [NSArray arrayWithObjects:[[contentViewController alloc] init], [[contentViewController alloc] init], nil];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
self.pageViewController.doubleSided = YES;
return UIPageViewControllerSpineLocationMid;
}
#end
The contentViewController is currently empty. This is what it looks like in simulator ...image
I want to create the following look mosaic app look. Is this a custom look? I was hoping this would be possible by setting UIPageViewController properties.
UIPageViewController does not provide any "look" at all. It's just a way of showing successive view controller's views. What you put in those views, or what you show behind/around/in front of the page view controller's view, is up to you. You want a book, draw a book.

Tab bar element onclick IOS

I have a master utility application embedded in a tab bar. Now, for this tab bar, i have the following.
#interface MainTabViewController : UITabBarController< UITabBarControllerDelegate>{
}
#end
#implementation MainTabViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
NSLog(#"One");
if(self.tabBarController.selectedIndex==1)
{
NSLog(#"clicked");
}
if (self.tabBarController.selectedIndex==2) {
NSLog(#"Helo");
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.tabBarController.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
The code is not reaching the didSelectViewController at all. I am new to IOS. Could anyone plz guide where i am going wrong??
Add delegate method to the UITabBarController
either using storyboard (if you are using)
or as it is UITabBarController do using
self.delegate = self ;

Different backgroundimages for UINavigationBar

Is it possible to use per-view backgroundImage in the UINavigationBar?
In the view loaded into the stack of UINavigationController, I tried :
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
[[self navigationController] setNavigationBarHidden:NO];
UINavigationItem* a = [self navigationItem];
[a setTitle:#"MY TITLE"];
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"mybar.png"] forBarMetrics:UIBarMetricsDefault];
}
But the image is not shown at all.
Is it possible to change the navigation bar image for every uiview loaded into the stack as it is loaded? In other words, different background image for different uiview loaded in the navigationcontroller.

How to implement UIPageViewController with a UIScrollView?

I took the Photo Scroller example from Apple's website and tried to implement my own Album by copying the code. Now, the UIScrollView is not visible. How do I make it appear?
The only code change that I made was in creating the UIPageViewController. In my case, it's a UIViewController that is opening it and not the AppDelegate.
#implementation BasePhotoViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nil bundle:nibBundleOrNil];
if (self) {
// kick things off by making the first page
PhotoViewController *pageZero = [PhotoViewController photoViewControllerForPageIndex:0];
if (pageZero != nil)
{
// assign the first page to the pageViewController (our rootViewController)
//UIPageViewController *pageViewController = (UIPageViewController *) [[UIApplication sharedApplication] keyWindow].rootViewController;
UIPageViewController *pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:0 navigationOrientation:0 options:nil];
//UIPageViewController *pageViewController = (UIPageViewController *)self.parentViewController;
pageViewController.dataSource = self;
[pageViewController setViewControllers:#[pageZero]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:NULL];
}
}
return self;
}
You are not adding the pageViewController's view as a subview of BasePhotoViewController's view. Your BasePhotoViewController class should look something like this. Note the code in viewDidLoad.
BasePhotoViewController.h:
#interface BasePhotoViewController : UIViewController <UIPageViewControllerDataSource>
#property (nonatomic, strong) UIPageViewController * pageViewController;
#end
BasePhotoViewController.m:
#import "BasePhotoViewController.h"
#import "PhotoViewController.h"
#implementation BasePhotoViewController
#synthesize pageViewController;
- (id)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
PhotoViewController *pageZero = [PhotoViewController photoViewControllerForPageIndex:0];
if (pageZero != nil)
{
self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:0
navigationOrientation:0
options:nil];
self.pageViewController.dataSource = self;
[self.pageViewController setViewControllers:#[pageZero]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:NULL];
}
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
}
# pragma mark - UIPageViewControllerDataSource
- (UIViewController *)pageViewController:(UIPageViewController *)pvc viewControllerBeforeViewController:(PhotoViewController *)vc
{
NSUInteger index = vc.pageIndex;
return [PhotoViewController photoViewControllerForPageIndex:(index - 1)];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pvc viewControllerAfterViewController:(PhotoViewController *)vc
{
NSUInteger index = vc.pageIndex;
return [PhotoViewController photoViewControllerForPageIndex:(index + 1)];
}
#end
Note: I've initialised the UIPageViewController in initWithCoder: because Apple's Photo Scroller code uses a storyboard. I removed the UIPageViewController from the storyboard and created a BasePhotoViewController in its place. If you are not loading BasePhotoViewController from a storyboard, you should move the code in initWithCoder: to the appropriate initialiser.
EDIT: See this sample project on github.

Resources