Here is what I did to get this to work.
First, create a two new files, TapDetectingWindow.h and TapDetectingWindow.m as follows:
Code:
//
// TapDetectingWindow.h
//
#import <UIKit/UIKit.h>
@protocol TapDetectingWindowDelegate
- (void)userDidTapWebView:(id)tapPoint;
@end
@interface TapDetectingWindow : UIWindow {
UIView *viewToObserve;
id <TapDetectingWindowDelegate> controllerThatObserves;
}
@property (nonatomic, retain) UIView *viewToObserve;
@property (nonatomic, assign) id <TapDetectingWindowDelegate> controllerThatObserves;
@end
and
Code:
//
// TapDetectingWindow.m
//
#import "TapDetectingWindow.h"
@implementation TapDetectingWindow
@synthesize viewToObserve;
@synthesize controllerThatObserves;
- (id)initWithViewToObserver:(UIView *)view andDelegate:(id)delegate {
if(self == [super init]) {
self.viewToObserve = view;
self.controllerThatObserves = delegate;
}
return self;
}
- (void)dealloc {
[viewToObserve release];
[super dealloc];
}
- (void)forwardTap:(id)touch {
[controllerThatObserves userDidTapWebView:touch];
}
- (void)sendEvent:(UIEvent *)event {
[super sendEvent:event];
if (viewToObserve == nil || controllerThatObserves == nil)
return;
NSSet *touches = [event allTouches];
if (touches.count != 1)
return;
UITouch *touch = touches.anyObject;
if (touch.phase != UITouchPhaseEnded)
return;
if ([touch.view isDescendantOfView:viewToObserve] == NO)
return;
CGPoint tapPoint = [touch locationInView:viewToObserve];
NSLog(@"TapPoint = %f, %f", tapPoint.x, tapPoint.y);
NSArray *pointArray = [NSArray arrayWithObjects:[NSString stringWithFormat:@"%f", tapPoint.x],
[NSString stringWithFormat:@"%f", tapPoint.y], nil];
if (touch.tapCount == 1) {
[self performSelector:@selector(forwardTap:) withObject:pointArray afterDelay:0.5];
}
else if (touch.tapCount > 1) {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(forwardTap:) object:pointArray];
}
}
Next, add a reference to import the TapDetectingWindow.h file in the header file of view controller in which you would like to animate/hide the navigation bar
Code:
#import "TapDetectingWindow.h"
Now change the default @interface line in the same file to make TapDetectingWindow the delegate
Code:
@interface <Your View Controller Name Here> : UIViewController<TapDetectingWindowDelegate> {
Now add a global instance for the TapDetectingWindow object in the same file
Code:
TapDetectingWindow *mWindow;
Finally, define a new public method in the same file that will allow you make things happen when the user taps on your view
Code:
-(void)userDidTapWebView:(id)touch;
Now, in the method file of your view controller, add a viewDidLoad method if it doesn't exist, or add the following lines to your existing method if it does exist. In my example, the view for which I want to the navbar to hide/show is called mainView. Change this to whatever your view is named.
Code:
- (void)viewDidLoad {
[super viewDidLoad];
mWindow = (TapDetectingWindow *)[[UIApplication sharedApplication].windows objectAtIndex:0];
mWindow.viewToObserve = mainView;
mWindow.controllerThatObserves = self;
}
In the same file, create a new method to handle the user taps. In the example below, I hide the nav bar when the user taps the screen and then show it again when they tap again. I store the state of the navbar in a global boolean called NavBarHidden. When NavBarHidden == NO, the navbar is hidden and vice versa. Be sure to define BOOL * NaVBarHidden; in your header file for this work. I've also included code to hide/show a bottom tool bar and the iphone status bar.
Code:
- (void)userDidTapWebView:(id)touch {
if (NaVBarHidden == NO) {
// Hide the navigation bar
[self.navigationController setNavigationBarHidden:YES animated:YES];
// Hide the tool bar
[self.navigationController setToolbarHidden:YES animated:YES];
// Hide the status bar
// [[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];
// Record the change
NaVBarHidden = YES;
} else {
// Show the navigation bar
[self.navigationController setNavigationBarHidden:NO animated:YES];
// Show the tool bar
[self.navigationController setToolbarHidden:NO animated:YES];
// Show the status bar
// [[UIApplication sharedApplication] setStatusBarHidden:NO animated:NO];
// Record the change
NaVBarHidden = NO;
}
NSLog(@"The value of the bool is %@\n", (NaVBarHidden ? @"YES" : @"NO"));
}
If you would like your view to fill the entire screen beneath your navigation controller, be sure to add the following lines to your -(void)loadView method
Code:
self.navigationController.navigationBar.translucent = YES;
self.navigationController.toolbar.translucent = YES;
Last but not least, open your MainWindow.xib file in IB and be sure to change the window of type UIWindow to TapDetectingWindow. None of this will work until that is done.
Good luck!