UIButton inside UINavigationController receives taps from wrong place - ios

I am trying to programmatically create a UIViewController subclass whose view includes some buttons, and then add that to a UINavigationController. When I do, you have to touch about 40 or 50 points above each button in order to trigger it (touching the buttons themselves does nothing). The distance between the button and the actual area you have to touch seems to match the height of the UINavigationController's nav bar, so I suspect that has something to do with it. Any suggestions on how to fix this? Here is the code that creates the window and the buttons (from my UIViewController subclass):
- (void)loadView
{
...
UIWindow* mainView = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease];
[mainView setBackgroundColor:[UIColor groupTableViewBackgroundColor]];
[mainView makeKeyAndVisible];
[self setView:mainView];
}
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton* encryptButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[encryptButton setTitle:#"Encrypt" forState:UIControlStateNormal];
[encryptButton setFrame:CGRectMake(([[self view] bounds].size.width - 150.0f)/2.0f,
([[self view] bounds].size.height - 120.0f)/2.0f, 150.0f, 40.0f)];
[encryptButton setBounds:CGRectMake(0.0f, 0.0f, 150.0f, 40.0f)];
[encryptButton addTarget:self action:#selector(encryptPressed:) forControlEvents:UIControlEventTouchUpInside];
[[self view] addSubview:encryptButton];
[encryptButton release];
UIButton* decryptButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[decryptButton setTitle:#"Decrypt" forState:UIControlStateNormal];
[decryptButton setFrame:CGRectMake(([[self view] bounds].size.width - 150.0f)/2.0f,
([[self view] bounds].size.height - 120.0f)/2.0f + 80.0f, 150.0f, 40.0f)];
[decryptButton addTarget:self action:#selector(decryptPressed:) forControlEvents:UIControlEventTouchUpInside];
[[self view] addSubview:decryptButton];
[decryptButton release];
}
Here's the code that sets up the UINavigationController:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
UUMainWindowViewController* mainWinController = [[UUMainWindowViewController alloc] init];
UINavigationController* mainNavController = [[UINavigationController alloc]
initWithRootViewController:mainWinController];
[mainNavController navigationBar].barStyle = UIBarStyleBlack;
[self.window setRootViewController:mainNavController];
[self.window makeKeyAndVisible];
return YES;
}

Figured out my own answer. Turns out this was a newbie mistake where I was constructing a UIWindow in my UIViewController when I really just need to construct a UIView instead. Apparently there should only ever be one UIWindow, so presumably this wasn't working because UIWindow was assuming it had the entire screen real estate to itself.

Related

Custom Navigation Bar in ios6 and ios7

I have a problem to which I can't found a solution right now. In my application I have multiple buttons in my NavigationBar which are required throughout the app, rather than creating the buttons in every view controller I want to make a sub class of UINavigationBar or UINavigationController(i don't know which one). So that whenever the user moves between the views the navigation bar always contains those buttons. I have searched very much till now regarding this but couldn't found anything worth.
Please suggest me a way to do so, thanks in advance.
#import "CustomNavBar.h"
#implementation CustomNavBar
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.tintColor=[UIColor greenColor];
}
return self;
}
- (void)drawRect:(CGRect)rect {
UIImage *image = [UIImage imageNamed:#"Custom-Nav-Bar-BG.png"];
[image drawInRect:CGRectMake(0, 0, 40, self.frame.size.height)];
UIButton *btn=[UIButton buttonWithType:UIButtonTypeContactAdd];
[btn drawRect:CGRectMake(42, 0, 40, self.frame.size.height )];
UIButton *btn2=[UIButton buttonWithType:UIButtonTypeContactAdd];
[btn2 drawRect:CGRectMake(82, 0, 40, self.frame.size.height )];
}
#end
You can subClass standard UINavigationBar to achieve this
#interface CustomNavigationBar : UINavigationBar
- (id)initWithFrame:(CGRect)frame;
#end
#implementation CustomNavigationBar
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UIButton *btn=[UIButton buttonWithType:UIButtonTypeContactAdd];
[btn addTarget:self action:#selector(<#selector#>) forControlEvents:<#(UIControlEvents)#>]
[self addSubview:btn];
...
...
}
return self;
}
- (void)drawRect:(CGRect)rect {
[[UIColor redColor] setFill];
UIRectFill(rect);
}
#end
To use this is StoryBoard or xib, simply change standard class name to CustomNavigationBar.
OR
If you want it programmatically
In AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen] bounds]];
UINavigationController *navVC = [[UINavigationController alloc] initWithNavigationBarClass:[CustomNavigationBar class] toolbarClass:nil];
UIStoryboard *mStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController *VC1 = [mStoryboard instantiateViewControllerWithIdentifier:#"VC"];
[navVC setViewControllers:[NSArray arrayWithObject:VC1] animated:NO];
[self. window setRootViewController:navVC];
[self. window makeKeyAndVisible];
return YES;
}

Add Original Custom View to the Window

I added my custom view to the window but it doesn't work. I tried to figure it out but it doesn't work well. (I created this project with the empty project template without using storyboards). This screen is supposed to show the red rectangle towards the bottom right corner of the screen.
I wanted to add my custom view showing red screen to the window, but it just shows the white screen.
AppDelegate.m:
//
// HypnosisterAppDelegate.m
// Hypnosister
//
// Created by TSH on 12/1/13.
// Copyright (c) 2013 TSH. All rights reserved.
//
#import "HypnosisterAppDelegate.h"
#import "HypnosisterViewController.h"
#import "HypnosisView.h"
#implementation HypnosisterAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
HypnosisterViewController *test = [[HypnosisterViewController alloc] initWithNibName:#"HypnosisterViewController" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:test];
self.window.rootViewController = nav;
CGRect viewFrame = CGRectMake(16, 24, 10, 15);
HypnosisView *view = [[HypnosisView alloc] initWithFrame:viewFrame];
[view setBackgroundColor:[UIColor redColor]];
[[self window] addSubview:view];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
#end
[edit]
I just messed up the ordering.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
HypnosisterViewController *test = [[HypnosisterViewController alloc] initWithNibName:#"HypnosisterViewController" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:test];
self.window.rootViewController = nav;
CGRect viewFrame = CGRectMake(160, 240, 100, 150);
HypnosisView *view = [[HypnosisView alloc] initWithFrame:viewFrame];
[view setBackgroundColor:[UIColor redColor]];
[[self window] addSubview:view];
return YES;
}
As you set navigationcontroller as rootviewcontroller so HypnosisterViewController will appear every time no doubts. If you want to add a custom view to have to add as a subview on the HypnosisterViewController.
HypnosisView *view = [[HypnosisView alloc] initWithFrame:viewFrame];
[view setBackgroundColor:[UIColor redColor]];
[test.view addSubview:view];
Hopefully it will work
#toshi You code is correct just you missed the ordering .Use this code it will work.Let me know if it doesn't work.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
HypnosisterViewController *test = [[HypnosisterViewController alloc] initWithNibName:#"HypnosisterViewController" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:test];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
CGRect viewFrame = CGRectMake(16, self.window.frame.size.height - 24, 10, 15);
HypnosisView *view = [[HypnosisView alloc] initWithFrame:viewFrame];
[view setBackgroundColor:[UIColor redColor]];
[[self window] addSubview:view];
self.window.backgroundColor = [UIColor whiteColor];
return YES;
}
There is two points
1- The coordinate of the view in iOS begin from top-left so this frame (16, 24, 10, 15) will in the top-left of the view as frame calculated as (x,y,width,height)
2- Window does not responds to device Orientation. It will be always Portrait. If you rotate your device you will need to re-calculate the view Coordinate.

adding UIViewcontroller's view to UIWindow does not show

I am trying to see a view with the following code where I am using storyboard however I did not make the uiviewcontroller's scene initial view controller.
This is the code I wrote in didFinishLaunchingWithOption of my AppDelegate.
UIWindow* window = [UIApplication sharedApplication].keyWindow;
abcViewController *controller = [[abcViewController alloc]init];
UIView *redView = [[UIView alloc] initWithFrame: CGRectMake ( [[UIScreen mainScreen] bounds].origin.x+30, [[UIScreen mainScreen] bounds].origin.y+30, 260, 400)];
[redView setBackgroundColor:[UIColor redColor]];
UIView *greenView = [[UIView alloc] initWithFrame: CGRectMake ( redView.frame.origin.x + 10.0f, redView.frame.origin.y + 10.0f, 180, 320)];
[greenView setBackgroundColor:[UIColor greenColor]];
[redView addSubview:greenView];
[controller.view addSubview:redView];
window.rootViewController = controller;
[window makeKeyAndVisible];
return YES;
First assign storyboard id to the abcViewController in storyboard eg."firstView".
Import the viewController in app delegate
In the storyboard, uncheck the "Is initial View Controller" attribute from the first view controller.
In the app's info.plist, remove the value of "Main storyboard file base name".
Instantiate the storyboard, create the window object and set initial view controller in the app delegate's application:didFinishLaunchingWithOptions: method
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
TestViewController *controller = [storyboard instantiateViewControllerWithIdentifier:#"firstView"];
UIView *redView = [[UIView alloc] initWithFrame: CGRectMake ( [[UIScreen mainScreen] bounds].origin.x+30, [[UIScreen mainScreen] bounds].origin.y+30, 260, 400)];
[redView setBackgroundColor:[UIColor redColor]];
UIView *greenView = [[UIView alloc] initWithFrame: CGRectMake ( redView.frame.origin.x + 10.0f, redView.frame.origin.y + 10.0f, 180, 320)];
[greenView setBackgroundColor:[UIColor greenColor]];
[redView addSubview:greenView];
[controller.view addSubview:redView];
self.window.rootViewController = controller;
[self.window makeKeyAndVisible];
return YES;
}

IOS UINavigationController, pushViewController not working

Good evening,
I currently have two UIViewControllers. My appDelegate looks like this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
struct CGRect rect = [[UIScreen mainScreen] bounds];
rect.origin.x = rect.origin.y = 0.0f;
_viewController = [[sandboxViewController alloc] init];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:_viewController];
_window = [[UIWindow alloc] initWithFrame:rect];
[_window makeKeyAndVisible];
[_window addSubview:nc.view];
return YES;
}
The viewController looks like this:
- (void)loadView {
self.view = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 480.0f)];
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.title = #"Master View";
}
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
[infoButton addTarget:self action:#selector(switchView:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:infoButton];
}
- (void)switchView:(id)obj {
if(![self navigationController])
NSLog(#"navigationController IS NIL!!!");
if(!_secondView)
_secondView = [[secondViewController alloc] init];
[self.navigationController pushViewController:_secondView animated:YES];
}
By clicking on the info button, that was added to the right side on the navigation bar, I want to switch to the secondView. This, however, is not happening because navigationController logs as nil ! What am I missing here?
Any help is truly appreciated!
You don't have to create the window, it should already exist.
//_window = [[UIWindow alloc] initWithFrame:rect]; //remove this line
[self.window makeKeyAndVisible]; //use the ivar
[self.window addSubview:nc.view];

programmatically add a UIButton to rootview, what am I doing wrong?

I have freshly setup app, just with a window an a root view (from the iOS single view application template, provided by XCode).
Now I try to add a button to it.
The according code looks like this:
- (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIButton* button0 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button0.frame = CGRectMake(140, 230, 40, 20);
[button0 setTitle:#"Exit" forState:UIControlStateNormal];
[button0 addTarget:self action:#selector(action) forControlEvents:UIControlEventTouchUpInside];
[self.viewController.view addSubview:button0];
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_iPhone" bundle:nil];
else
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_iPad" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
When I start the app, I can only see the empty view.
However, when comment out the line, which adds the view as root to the window and instead directly add the button to the window, then I can see the button just fine.
So why isn't this working with the view?
The problem is that, you are adding button0 as subview of self.viewController.view even before allocating the viewController.
By the time you call addSubview: method, self.viewController is nil. So, the button is not added to the viewController. You should add the button after you allocate the viewController.
self.viewController = [[ViewController alloc]...
[self.viewController.view addSubview:button0];
At first, create the root viewcontroller, later add subviews to it. You did it the other way round.

Resources