I want to implement slide menu in my iOS app like drawer (Andriod). I went through a tutorial, but all of them are using third party libraries. Is there any possibility to create a custom slide menu. I tried to create it with the following code, but it's only working with xib file:
- (IBAction)sidemenu:(id)sender
{
[UIView animateWithDuration:0.50f animations:^{
view.frame = self.view.frame;
} completion:^(BOOL finished) {
swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(SwipGestureLeftAction:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeLeft];
}];
}
- (void)SwipGestureAction
{
UISwipeGestureRecognizer *swiperight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(SwipGestureRightAction:)];
swiperight.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swiperight];
}
#pragma mark AddSwipeGestureLeftAndRight
- (void)SwipGestureRightAction:(UISwipeGestureRecognizer *)swipeRight
{
[UIView animateWithDuration:0.50f animations:^{
view.frame = self.view.frame;
} completion:^(BOOL finished) {
swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(SwipGestureLeftAction:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeLeft];
}];
}
- (void)SwipGestureLeftAction:(UISwipeGestureRecognizer *)swipeRight
{
[UIView animateWithDuration:0.50f animations:^{
[view setFrame:CGRectMake(self.view.frame.origin.x - self.view.frame.size.width, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height)];
} completion:^(BOOL finished){
[self.view removeGestureRecognizer:swipeLeft];
}];
}
Here is what I have for you:
I made a super class for all my slide menus in all projects. It manages the showing and hiding of the slide menu, and handles orientation changes. It slides in from left on top of the current view, and it partially obscures the remainder of the view with a dark transparent background.
If you ever need other behaviour (like pushing out the current view) just override the animation part.
My slide menu is a Singleton because in our applications we only use one slide menu on every screen.
#import <UIKit/UIKit.h>
#interface IS_SlideMenu_View : UIView <UIGestureRecognizerDelegate>
{
UIView* transparentBgView;
BOOL hidden;
int lastOrientation;
}
#property (strong, nonatomic) UIView *menuContainerV;
+ (id)sharedInstance;
- (BOOL)isShown;
- (void)hideSlideMenu;
- (void)showSlideMenu;
#end
#import "IS_SlideMenu_View.h"
#implementation IS_SlideMenu_View
+ (id)sharedInstance
{
static id _sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstance = [[[self class] alloc] init];
});
return _sharedInstance;
}
- (instancetype)initWithFrame:(CGRect)frame
{
frame = [[[UIApplication sharedApplication] delegate] window].frame;
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
transparentBgView = [[UIView alloc] initWithFrame:frame];
[transparentBgView setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.6]];
[transparentBgView setAlpha:0];
transparentBgView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(gestureRecognized:)];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(gestureRecognized:)];
[transparentBgView addGestureRecognizer:tap];
[transparentBgView addGestureRecognizer:pan];
[self addSubview:transparentBgView];
frame.size.width = 280;
self.menuContainerV = [[UIView alloc] initWithFrame:frame];
CALayer *l = self.menuContainerV.layer;
l.shadowColor = [UIColor blackColor].CGColor;
l.shadowOffset = CGSizeMake(10, 0);
l.shadowOpacity = 1;
l.masksToBounds = NO;
l.shadowRadius = 10;
self.menuContainerV.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[self addSubview: self.menuContainerV];
hidden = YES;
}
//----- SETUP DEVICE ORIENTATION CHANGE NOTIFICATION -----
UIDevice *device = [UIDevice currentDevice];
[device beginGeneratingDeviceOrientationNotifications];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:device];
lastOrientation = [[UIDevice currentDevice] orientation];
return self;
}
//********** ORIENTATION CHANGED **********
- (void)orientationChanged:(NSNotification *)note
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if(orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight){
NSLog(#"%ld",orientation);
if(!hidden && lastOrientation != orientation){
[self hideSlideMenu];
hidden = YES;
lastOrientation = orientation;
}
}
}
- (void)showSlideMenu {
UIWindow* window = [[[UIApplication sharedApplication] delegate] window];
self.frame = CGRectMake(0, 0, window.frame.size.width, window.frame.size.height);
[self.menuContainerV setTransform:CGAffineTransformMakeTranslation(-window.frame.size.width, 0)];
[window addSubview:self];
// [[UIApplication sharedApplication] setStatusBarHidden:YES];
[UIView animateWithDuration:0.5 animations:^{
[self.menuContainerV setTransform:CGAffineTransformIdentity];
[transparentBgView setAlpha:1];
} completion:^(BOOL finished) {
NSLog(#"Show complete!");
hidden = NO;
}];
}
- (void)gestureRecognized:(UIGestureRecognizer *)recognizer
{
if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]) {
[self hideSlideMenu];
} else if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
static CGFloat startX;
if (recognizer.state == UIGestureRecognizerStateBegan) {
startX = [recognizer locationInView:self.window].x;
} else
if (recognizer.state == UIGestureRecognizerStateChanged) {
CGFloat touchLocX = [recognizer locationInView:self.window].x;
if (touchLocX < startX) {
[self.menuContainerV setTransform:CGAffineTransformMakeTranslation(touchLocX - startX, 0)];
}
} else
if (recognizer.state == UIGestureRecognizerStateEnded) {
[self hideSlideMenu];
}
}
}
- (void)hideSlideMenu
{
UIWindow* window = [[[UIApplication sharedApplication] delegate] window];
window.backgroundColor = [UIColor clearColor];
[UIView animateWithDuration:0.5 animations:^{
[self.menuContainerV setTransform:CGAffineTransformMakeTranslation(-self.window.frame.size.width, 0)];
[transparentBgView setAlpha:0];
} completion:^(BOOL finished) {
[self removeFromSuperview];
[self.menuContainerV setTransform:CGAffineTransformIdentity];
// [[UIApplication sharedApplication] setStatusBarHidden:NO];
hidden = YES;
NSLog(#"Hide complete!");
}];
}
- (BOOL)isShown
{
return !hidden;
}
#end
Subclasses only need to add subviews to the menuContainerV view, and manage them.
An example:
I created a subclass that has an header view and a table view as its content. I created the content view in a xib, and the owner of the xib is this subclass. This way I can bind outlets to the xib.
#import "IS_SlideMenu_View.h"
#interface CC_SlideMenu_View : IS_SlideMenu_View<UITableViewDelegate, UITableViewDataSource>
#property (weak, nonatomic) IBOutlet UIView *headerView;
#property (weak, nonatomic) IBOutlet UITableView *tableView;
...
#end
When the slide menu gets instantiated I load the xib and add the content view to the menuContainerV view.
#import "CC_SlideMenu_View.h"
#implementation CC_SlideMenu_View
- (instancetype)init
{
self = [super init];
if (self) {
UIView *v = [[[NSBundle mainBundle] loadNibNamed:#"CC_SlideMenu_View" owner:self options:nil] firstObject];
v.frame = self.menuContainerV.bounds;
[self.menuContainerV addSubview:v];
self.tableView.backgroundColor = [UIColor darkGrayColor];
}
return self;
}
...
#end
The result is something like this.
Related
Im new in OOP and I've read some tutorials and books. I have the concept more or less clear but I haven't seen many examples. I've made a simple webView app which only displays a website and got some tabs and push notifications. It's not the big deal. Almost all the code from father class can be reused, and no need to rewrite it, so I've made some inheritance and overriding solutions to childrens, but I'm would like to know if the way I did it is the correct approach to object oriented way, also with the design and even with the code documentation. I need to show this code in a future job interview and I would like to refine it and also learn about experts from here with with more experience than I have.
Any help would be highly appreciated and many thanks!
This is my father class:
//
// FirstViewController.h
#import <UIKit/UIKit.h>
#import "iAd/iAd.h"
#interface FirstViewController : UIViewController <UIWebViewDelegate,UIGestureRecognizerDelegate, ADBannerViewDelegate, UIScrollViewDelegate>
#property (strong, nonatomic) IBOutlet UITabBarItem *tabInicio;
+(void)viewController:(NSString*)link;
-(void)configureView:(UIViewController*)vista;
-(void)iAdDisplay:(UIViewController*)vista;
-(void)autoResizeWhenRotates:(UIViewController*)vista;
-(void)configureWebView:(UIViewController *)vista withUrlLink:(NSURL *)url;
-(void)showHideStatusBar:(UIViewController*)vista;
-(void)addGestures:(UIViewController*)vista;
-(void)configureToolBar:(UIViewController*)vista;
-(void)addIndicator:(UIViewController*)vista;
#end
And the implementation file:
//
// FirstViewController.m
// push
//
#import "FirstViewController.h"
#interface FirstViewController ()
#property UIActivityIndicatorView *indicator;
#property UIToolbar *cToolBar;
#property BOOL isHidden;
#end
#implementation FirstViewController
static UITabBarController *static_Tab = nil;
static UIWebView* static_iVar = nil;
- (void)viewDidLoad {
[super viewDidLoad];
[self configureView:self];
//configure autoresize when device rotate
NSURL *url = [NSURL URLWithString:#"http://hnoslopez.com"];
[self configureStatic_iVar:self withUrlLink:url];
//Set tab bar icons
[[[self.tabBarController.viewControllers objectAtIndex:1] tabBarItem]setImage:[UIImage imageNamed:#"nosotros.png"]];
[[[self.tabBarController.viewControllers objectAtIndex:2] tabBarItem]setImage:[UIImage imageNamed:#"catalogo.png"]];
[[[self.tabBarController.viewControllers objectAtIndex:3] tabBarItem]setImage:[UIImage imageNamed:#"blog.png"]];
self.tabBarController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.tabBarController.view.autoresizesSubviews = YES;
//Set first tab
_tabInicio = [[UITabBarItem alloc] initWithTitle:#"Inicio" image:[UIImage imageNamed:#"inicioIcon.png"] tag:0];
[[UITabBar appearance] setSelectedImageTintColor:[UIColor greenColor]];
[self.tabBarController setSelectedIndex:0];
self.tabBarItem = _tabInicio;
}
-(void)configureView:(UIViewController *)vista{
//configure toolbar
[self configureToolBar:vista];
//show hide status bar with a gesture recognizer and an animation
[self showHideStatusBar:vista];
//iAd display
[self iAdDisplay:vista];
//auto resizing when device rotates
[self autoResizeWhenRotates:vista];
//Add gestures
[self addGestures:vista];
//Add Indicator
[self addIndicator:vista];
}
-(void)configureToolBar:(UIViewController *)vista{
//Add a toolbar, back and reload button...
UIToolbar *cToolBar = [[UIToolbar alloc] init];
//auto resizing
cToolBar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingNone;
cToolBar.autoresizesSubviews = YES;
cToolBar.frame = CGRectMake(0, 0, vista.view.frame.size.width, 44);
NSMutableArray *items = [[NSMutableArray alloc] init];
//Set toolbar properties..
[cToolBar setBarStyle:UIBarStyleBlack];
[cToolBar setTranslucent:YES ];
[cToolBar setTintColor:[UIColor greenColor]];
//Back Button..
NSString *backArrowString = #"\U000025C0\U0000FE0E AtrĂ¡s"; //BLACK LEFT-POINTING TRIANGLE PLUS VARIATION SELECTOR
UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithTitle:backArrowString style:UIBarButtonItemStyleDone target:nil action:#selector(goBack)];
//Reload button..
UIBarButtonItem *right = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:nil action:#selector(refreshControl)];
[right setTintColor:[UIColor greenColor]];
//Flexible space between buttons..
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[items addObject:back];
[items addObject:flexibleSpace];
[items addObject:right];
[cToolBar setItems:items animated:NO];
[vista.view addSubview:cToolBar];
}
-(void)showHideStatusBar:(UIViewController *)vista{
//Animation performed to hide/show bar when slide your finger..
if ([vista respondsToSelector:#selector(setNeedsStatusBarAppearanceUpdate)]) {
// iOS 7
[vista performSelector:#selector(setNeedsStatusBarAppearanceUpdate)];
} else {
// iOS 6
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
}
}
-(void)iAdDisplay:(UIViewController*)vista{
//Display iAd..
[vista setCanDisplayBannerAds:YES];
ADBannerView * adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
adView.frame = CGRectOffset(adView.frame, 0, 44);
adView.delegate = self;
//resizing
adView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
adView.autoresizesSubviews = YES;
[vista.view addSubview:adView];
}
-(void)autoResizeWhenRotates:(UIViewController*)vista{
vista.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
vista.view.autoresizesSubviews = YES;
}
-(void)addGestures:(UIViewController*)vista{
//SWIPE DOWN
UISwipeGestureRecognizer *gest1 = [[UISwipeGestureRecognizer alloc] initWithTarget:vista action:#selector(hideTabBar:)];
gest1.delegate = self;
[gest1 setDirection:UISwipeGestureRecognizerDirectionDown];
[vista.view addGestureRecognizer:gest1];
//SWIPE UP
UISwipeGestureRecognizer *gest2 = [[UISwipeGestureRecognizer alloc] initWithTarget:vista action:#selector(showTabBar:)];
gest2.delegate = self;
[gest2 setDirection:UISwipeGestureRecognizerDirectionUp];
[vista.view addGestureRecognizer:gest2];
}
-(void)addIndicator:(UIViewController *)vista{
//loading indicator
// _indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
UIActivityIndicatorView* indicador = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[indicador setCenter:vista.view.center];
[indicador setHidesWhenStopped:YES];
//resizing
indicador.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
indicador.autoresizesSubviews = YES;
[vista.view addSubview:indicador];
[indicador startAnimating];
}
-(void)configureWebView:(UIViewController *)vista withUrlLink:(NSURL *)url{
//Children method to configure children webViews...
float width = [UIScreen mainScreen].bounds.size.width;
float height = [UIScreen mainScreen].bounds.size.height;
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, width,height)];
webView.delegate = self;
//ADD Delegate to disable lateral scroll
webView.scrollView.delegate = self;
//auto resizing
webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
webView.autoresizesSubviews = YES;
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webView loadRequest:requestObj];
[vista.view addSubview:webView];
}
-(void)configureStatic_iVar:(UIViewController *)vista withUrlLink:(NSURL *)url{
//Configure father class webView...
float width = [UIScreen mainScreen].bounds.size.width;
float height = [UIScreen mainScreen].bounds.size.height;
static_iVar = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, width,height)];
static_iVar.delegate = self;
//ADD Delegate to disable lateral scroll
static_iVar.scrollView.delegate = self;
//auto resizing
static_iVar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
static_iVar.autoresizesSubviews = YES;
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[static_iVar loadRequest:requestObj];
[vista.view addSubview:static_iVar];
}
#pragma - mark selectors
-(void)goBack{
NSArray *subviews = [self.view subviews];
for (UIView *subview in subviews){
if([subview isKindOfClass:[UIWebView class]] && [subview respondsToSelector:#selector(goBack)])
{
[subview performSelector:#selector(goBack)];
}
}
}
-(void)refreshControl{
[super viewDidAppear:YES];
//iterate an array of subviews and finds indicator
NSArray *subviews = [self.view subviews];
for (UIView *subview in subviews)
{
if([subview isKindOfClass:[UIActivityIndicatorView class]] && [subview respondsToSelector:#selector(startAnimating)])
{
[subview performSelector:#selector(startAnimating)];
}
if([subview isKindOfClass:[UIWebView class]] && [subview respondsToSelector:#selector(reload)])
{
[subview performSelector:#selector(reload)];
}
}
}
- (void) hideTabBar:(UITabBarController *) tabbarcontroller
{
//Perform animation to hide tab bar
CGRect screenRect = [[UIScreen mainScreen] bounds];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
float fHeight = screenRect.size.height;
for(UIView *view in self.tabBarController.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
}
}
[UIView commitAnimations];
}
- (void) showTabBar:(UITabBarController *) tabbarcontroller
{
//Perform animation to show tab bar..
CGRect screenRect = [[UIScreen mainScreen] bounds];
float fHeight = screenRect.size.height - self.tabBarController.tabBar.frame.size.height;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in self.tabBarController.view.subviews)
{
if([view isKindOfClass:[UITabBar class]] )
{
[view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
}
}
[UIView commitAnimations];
}
+(void)viewController:(NSString*)link{
//Loads push notification links in first tab..
NSURL *url = [NSURL URLWithString:link];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[static_iVar loadRequest:requestObj];
}
#pragma mark - delegate methods
- (void)webViewDidStartLoad:(UIWebView *)webView
{
//iterate an array of subviews and finds indicator
NSArray *subviews = [self.view subviews];
for (UIView *subview in subviews)
{
if([subview isKindOfClass:[UIActivityIndicatorView class]] && [subview respondsToSelector:#selector(startAnimating)])
{
[subview performSelector:#selector(startAnimating)];
}
}
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
//iterate an array of subviews and finds indicator
NSArray *subviews = [self.view subviews];
if([subviews count] == 0)
{
return;
}
else
{
for (UIView *subview in subviews)
{
if([subview isKindOfClass:[UIActivityIndicatorView class]] && [subview respondsToSelector:#selector(stopAnimating)])
{
[subview performSelector:#selector(stopAnimating)];
}
}
}
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//iterate an array of subviews and finds indicator
NSArray *subviews = [self.view subviews];
if([subviews count] == 0)
{
return;
}
else
{
for (UIView *subview in subviews)
{
if([subview isKindOfClass:[UIActivityIndicatorView class]] && [subview respondsToSelector:#selector(stopAnimating)])
{
[subview performSelector:#selector(stopAnimating)];
}
}
}
CGSize contentSize = webView.scrollView.contentSize;
CGSize viewSize = self.view.bounds.size;
float rw = viewSize.width / contentSize.width;
webView.scrollView.minimumZoomScale = rw;
webView.scrollView.maximumZoomScale = rw;
webView.scrollView.zoomScale = rw;
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
return TRUE;
}
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
return YES;
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
[scrollView setContentOffset:CGPointMake(0, scrollView.contentOffset.y)];
}
- (BOOL)prefersStatusBarHidden {
return YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
And this is a children viewController:
//
// SecondViewController.h
//
#import <UIKit/UIKit.h>
#import "iAd/iAd.h"
#import "FirstViewController.h"
#interface secondViewController : FirstViewController <UIWebViewDelegate,UIGestureRecognizerDelegate,ADBannerViewDelegate, UIScrollViewDelegate>
#property (weak, nonatomic) IBOutlet UIWebView *secondView;
#property (strong, nonatomic) IBOutlet UITabBarItem *secondTab;
#end
Implementation file:
//
// SecondViewController.m
//
//
#import "secondViewController.h"
#import "iAd/iAd.h"
#interface secondViewController ()
#property UIActivityIndicatorView *indicador;
#end
#implementation secondViewController
- (void)viewDidLoad {
[super viewDidLoad];
[super configureView:self];
//configure webView
NSURL *url = [NSURL URLWithString:#"http://hnoslopez.com/nosotros/"];
[self configureWebView:self withUrlLink:url];
//Configure second tab
_secondTab = [[UITabBarItem alloc] initWithTitle:#"Nosotros" image:[UIImage imageNamed:#"nosotros.png"] tag:1];
[[UITabBar appearance] setSelectedImageTintColor:[UIColor greenColor]];
[self.tabBarController setSelectedIndex:1];
self.tabBarItem = _secondTab;
}
- (BOOL)prefersStatusBarHidden {
return YES;
}
-(void)goBack{
//reloads webView
NSArray *subviews = [self.view subviews];
for (UIView *subview in subviews){
if([subview isKindOfClass:[UIWebView class]] && [subview respondsToSelector:#selector(goBack)])
{
[subview performSelector:#selector(goBack)];
}
}
}
-(void)refreshControl{
[super viewDidAppear:YES];
//iterate an array of subviews and finds indicator
NSArray *subviews = [self.view subviews];
if([subviews count] == 0)
{
return;
}
else
{
for (UIView *subview in subviews)
{
//start animating indicator
if([subview isKindOfClass:[UIActivityIndicatorView class]] && [subview respondsToSelector:#selector(startAnimating)])
{
[subview performSelector:#selector(startAnimating)];
}
//reloads webView
if([subview isKindOfClass:[UIWebView class]] && [subview respondsToSelector:#selector(reload)])
{
[subview performSelector:#selector(reload)];
}
}
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
//iterate an array of subviews and finds indicator
NSArray *subviews = [self.view subviews];
if([subviews count] == 0)
{
return;
}
else
{
for (UIView *subview in subviews)
{
if([subview isKindOfClass:[UIActivityIndicatorView class]] && [subview respondsToSelector:#selector(startAnimating)])
{
[subview performSelector:#selector(startAnimating)];
}
}
}
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
//iterate an array of subviews and finds indicator
NSArray *subviews = [self.view subviews];
if([subviews count] == 0)
{
return;
}
else
{
for (UIView *subview in subviews)
{
if([subview isKindOfClass:[UIActivityIndicatorView class]] && [subview respondsToSelector:#selector(stopAnimating)])
{
[subview performSelector:#selector(stopAnimating)];
}
}
}
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//iterate an array of subviews and finds indicator
NSArray *subviews = [self.view subviews];
if([subviews count] == 0)
{
return;
}
else
{
for (UIView *subview in subviews)
{
if([subview isKindOfClass:[UIActivityIndicatorView class]] && [subview respondsToSelector:#selector(stopAnimating)])
{
[subview performSelector:#selector(stopAnimating)];
}
}
}
CGSize contentSize = webView.scrollView.contentSize;
CGSize viewSize = self.view.bounds.size;
float rw = viewSize.width / contentSize.width;
webView.scrollView.minimumZoomScale = rw;
webView.scrollView.maximumZoomScale = rw;
webView.scrollView.zoomScale = rw;
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
return TRUE;
}
- (void) hideTabBar:(UITabBarController *) tabbarcontroller
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
float fHeight = screenRect.size.height;
for(UIView *view in self.tabBarController.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
}
}
[UIView commitAnimations];
}
- (void) showTabBar:(UITabBarController *) tabbarcontroller
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
float fHeight = screenRect.size.height - self.tabBarController.tabBar.frame.size.height;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
for(UIView *view in self.tabBarController.view.subviews)
{
if([view isKindOfClass:[UITabBar class]] )
{
[view setFrame:CGRectMake(view.frame.origin.x, fHeight, view.frame.size.width, view.frame.size.height)];
}
}
[UIView commitAnimations];
}
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
return YES;
}
#pragma mark resuelve problema de que la pagina hace scroll horizontal
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
[scrollView setContentOffset:CGPointMake(0, scrollView.contentOffset.y)];
}
#end
I've read multiple solutions here on SO, but they all don;t seem to work in my case.
I've got a class NotificationBar:
.h file:
#interface NotificationBar : UIView <UIGestureRecognizerDelegate>
#property (strong, nonatomic) UILabel *messageLabel;
- (id)initWithFrame:(CGRect)frame message:(NSString *)message;
- (void) show:(int)duration;
#end
.m file:
#import "NotificationBar.h"
#implementation NotificationBar
#synthesize messageLabel;
- (id)initWithFrame:(CGRect)frame message:(NSString *)message
{
self = [super initWithFrame:frame];
if (self)
{
self.alpha = 0;
self.backgroundColor = [UIColor cabmanBlue];
self.userInteractionEnabled = YES;
self.messageLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.bounds.origin.x + 5, 0 , self.bounds.size.width - 10, self.bounds.size.height)];
[self.messageLabel setBackgroundColor:[UIColor clearColor]];
[self.messageLabel setTextColor:[UIColor whiteColor]];
[self.messageLabel setFont:[UIFont boldSystemFontOfSize:14]];
[self.messageLabel setNumberOfLines:2];
self.messageLabel.text = message;
[self addSubview:messageLabel];
UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismiss:)];
tapRec.delegate = self;
tapRec.cancelsTouchesInView = NO;
[self addGestureRecognizer:tapRec];
}
return self;
}
- (void) show:(int)duration
{
[[[[[UIApplication sharedApplication] keyWindow] subviews] lastObject] addSubview:self];
[UIView animateWithDuration:0.5 animations:^{ self.alpha = 1; } completion:^(BOOL finished) {
[UIView animateWithDuration:0.5 delay:duration options:UIViewAnimationOptionCurveLinear animations:^{ self.alpha = 0;} completion:^(BOOL finished)
{
if(finished) [self removeFromSuperview];
}];
}];
}
- (void) dismiss:(UITapGestureRecognizer *)gesture
{
[self.layer removeAllAnimations];
[UIView animateWithDuration:0.5 animations:^{ self.alpha = 0; } completion:^(BOOL finished) {
if(finished)
{
[self removeFromSuperview];
}
}];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
#end
And I use the class in the following way:
- (void) displayNotificationMessage:(NSString *)message withSound:(BOOL) withSound
{
UIView *topView = [self.window.subviews lastObject];
[[[NotificationBar alloc] initWithFrame:CGRectMake(topView.bounds.origin.x,
64,
topView.bounds.size.width,
40)
message:message] show:10];
if(withSound) AudioServicesPlaySystemSound(1007);
}
The view is always presented and shown. The dismiss function isn't triggered and it seems it doesn't respond to anything. displayNotificationMessage is placed in AppDelegate. displayNotificationMessage is some times used when a viewcontroller with a mapview is displayed or in a UITableViewController. You could say it has to work the same way as UIAlertView: always presented no matter in which screen the user is.
Does anyone see an error or something?
Thank in advance!
Your UILabel takes over almost your entire view bounds:
self.messageLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.bounds.origin.x + 5, 0 , self.bounds.size.width - 10, self.bounds.size.height)];
You may try reducing it's size and then see if the gesture works in the other locations or you can try adding the gesture to the label
[self.messageLabel addGestureRecognizer:singleTap];
I just tried your code on a custom UIView and it works just fine. Having the UILabel as a subview has no effect, it responds well. To me it looks like you probably have either another UIView put over this one (which makes this one buried and therefore unresponsive) or you have another Tap Gesture registered in your superview.
I have created a SlidingViewController which has a Main, Right, and Left view controllers. Now I want to add a new function/method that is called whenever one of the RightViewController's table view cell is clicked to switch the main view controller to what ever view controller is linked with that table view cell at indexpath.row. The new view controller should still be able to have this right and left view controller available. Anyone have any experience creating their own SlidingViewController or MenuViewController that can help out on how I should approach this? Any help will be gratefully appreciated. Thank you in advance.
SlidingViewController.h
#interface SlidingViewController : UIViewController <UIGestureRecognizerDelegate>
#property (retain) UIViewController *mainViewController;
#property (retain) UIViewController *leftViewController;
#property (retain) UIViewController *rightViewController;
#property (retain) NSNumber *leftSwipeEnabled;
#property (assign) BOOL leftDrawerVisible;
#property (retain) NSNumber *rightSwipeEnabled;
#property (assign) BOOL rightDrawerVisible;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil mainViewController:(UIViewController *)main leftViewController:(UIViewController *)left andRightViewController:(UIViewController *)right;
-(void)toggleLeftDrawer;
-(void)toggleRightDrawer;
#end
SlidingViewController.m
#implementation SlidingViewController
#synthesize mainViewController, leftViewController, rightViewController;
#synthesize leftDrawerVisible, rightDrawerVisible;
#synthesize leftSwipeEnabled, rightSwipeEnabled;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil mainViewController:(UIViewController *)main leftViewController:(UIViewController *)left andRightViewController:(UIViewController *)right
{
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
{
mainViewController = main;
leftViewController = left;
rightViewController = right;
leftSwipeEnabled = [NSNumber numberWithBool:NO];
rightSwipeEnabled = [NSNumber numberWithBool:NO];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self addChildViewController:self.mainViewController];
[self.view addSubview:[self.mainViewController view]];
self.mainViewController.view.frame = self.view.frame;
[self.mainViewController didMoveToParentViewController:self];
self.mainViewController.view.layer.shadowColor = [UIColor blackColor].CGColor;
self.mainViewController.view.layer.shadowOpacity = 0.2f;
self.mainViewController.view.layer.shadowRadius = 5.0f;
CGPathRef path = [UIBezierPath bezierPathWithRect:self.mainViewController.view.bounds].CGPath;
self.mainViewController.view.layer.shadowPath = path;
if(self.leftViewController != nil)
{
UISwipeGestureRecognizer *leftSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipe:)];
leftSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
leftSwipeRecognizer.delegate = self;
[self.mainViewController.view addGestureRecognizer:leftSwipeRecognizer];
}
if(self.rightViewController != nil)
{
UISwipeGestureRecognizer *rightSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipe:)];
rightSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
rightSwipeRecognizer.delegate = self;
[self.mainViewController.view addGestureRecognizer:rightSwipeRecognizer];
}
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self layoutShadowWithDuration:0];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
if(self.leftDrawerVisible)
[self toggleLeftDrawer];
else if(self.rightDrawerVisible)
[self toggleRightDrawer];
}
-(BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
-(void)handleSwipe:(UISwipeGestureRecognizer *)recognizer
{
if(recognizer.state == UIGestureRecognizerStateEnded)
{
if(recognizer.direction == UISwipeGestureRecognizerDirectionRight && [self.leftSwipeEnabled boolValue])
[self toggleLeftDrawer];
else if(recognizer.direction == UISwipeGestureRecognizerDirectionLeft && [self.rightSwipeEnabled boolValue])
[self toggleRightDrawer];
}
}
-(void)toggleLeftDrawer
{
if (self.rightDrawerVisible)
{
return;
}
if(self.leftDrawerVisible)
{
[UIView animateWithDuration:0.2
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
self.mainViewController.view.frame = CGRectMake(0.0, 0.0, self.mainViewController.view.frame.size.width, self.mainViewController.view.frame.size.height);}
completion:^(BOOL finished)
{
[self.leftViewController.view removeFromSuperview];
[self.leftViewController willMoveToParentViewController:nil];
[self.leftViewController removeFromParentViewController];
}];
self.leftDrawerVisible = NO;
self.mainViewController.view.userInteractionEnabled = YES;
}
else
{
[self addChildViewController:self.leftViewController];
[self.view insertSubview:[self.leftViewController view] belowSubview:[self.mainViewController view]];
[self.leftViewController didMoveToParentViewController:self];
CGPathRef path = [UIBezierPath bezierPathWithRect:self.mainViewController.view.bounds].CGPath;
self.mainViewController.view.layer.shadowPath = path;
self.mainViewController.view.layer.shadowOffset = CGSizeMake(-3, 0);
NSInteger width = 260;
if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
width = 320;
self.leftViewController.view.frame = CGRectMake(0, 0, width, self.view.bounds.size.height);
[UIView animateWithDuration:0.2
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{ self.mainViewController.view.frame = CGRectMake(width, 0, self.mainViewController.view.frame.size.width, self.mainViewController.view.frame.size.height); }
completion:^(BOOL finished) { self.leftViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin; }];
self.leftDrawerVisible = YES;
self.mainViewController.view.userInteractionEnabled = NO;
}
}
-(void)toggleRightDrawer
{
if(self.leftDrawerVisible)
return;
if(self.rightDrawerVisible)
{
[UIView animateWithDuration:0.2
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
self.mainViewController.view.frame = CGRectMake(0.0, 0.0, self.mainViewController.view.frame.size.width, self.mainViewController.view.frame.size.height);
}
completion:^(BOOL finished){
[self.rightViewController.view removeFromSuperview];
[self.rightViewController willMoveToParentViewController:nil];
[self.rightViewController removeFromParentViewController];
}];
self.rightDrawerVisible = NO;
self.mainViewController.view.userInteractionEnabled = YES;
}
else
{
[self addChildViewController:self.rightViewController];
[self.view insertSubview:[self.rightViewController view] belowSubview:[self.mainViewController view]];
[self.rightViewController didMoveToParentViewController:self];
CGPathRef path = [UIBezierPath bezierPathWithRect:self.mainViewController.view.bounds].CGPath;
self.mainViewController.view.layer.shadowPath = path;
self.mainViewController.view.layer.shadowOffset = CGSizeMake(3, 0);
NSInteger width = 260;
if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
width = 320;
self.rightViewController.view.frame = CGRectMake(self.view.bounds.size.width- width, 0, width, self.view.bounds.size.height);
[UIView animateWithDuration:0.2 delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
self.mainViewController.view.frame = CGRectMake(-width, 0, self.mainViewController.view.frame.size.width, self.mainViewController.view.frame.size.height);
}
completion:^(BOOL finished){
self.rightViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin;
}];
self.rightDrawerVisible = YES;
self.mainViewController.view.userInteractionEnabled = NO;
}
}
-(void) layoutShadowWithDuration:(NSTimeInterval)duration
{
CGPathRef oldShadowPath = self.mainViewController.view.layer.shadowPath;
if (oldShadowPath)
{
CFRetain(oldShadowPath);
}
// Update shadow path for the view
CGPathRef path = [UIBezierPath bezierPathWithRect:self.mainViewController.view.bounds].CGPath;
self.mainViewController.view.layer.shadowPath = path;
// You would think setting duration to 0 would cause the animation added below to not animate. You would be wrong.
if (duration != 0)
{
if (oldShadowPath)
{
[self.mainViewController.view.layer addAnimation:((^ {
CABasicAnimation *transition = [CABasicAnimation animationWithKeyPath:#"shadowPath"];
transition.fromValue = (__bridge id)oldShadowPath;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.duration = duration;
return transition;
})()) forKey:#"transition"];
CFRelease(oldShadowPath);
}
else
if (oldShadowPath)
CFRelease(oldShadowPath);
}
else
if (oldShadowPath)
CFRelease(oldShadowPath);
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self layoutShadowWithDuration:duration];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
You can simply do this by "Delegation Design Pattern"
In RightViewController.h add the following lines.
#protocol RightViewControllerDelegate <NSObject>
#required
- (void)somethingClicked : (id)theObject;
#end
#interface RightViewController : UIViewController
#property (nonatomic, assign) id<RightViewControllerDelegate> delegate;
#end
In RightViewController.m add the following lines.
- (void)somethingClicked : (id)theObject
{
[_delegate somethingClicked:theObject];
}
Update MainViewController.h with the following code.
#interface MainViewController : UIViewController <RightViewControllerDelegate>
And Finally add the following code in the MainViewController.m
- (void)somethingClicked : (id)theObject
{
// Perform Your Task
}
I have a parent view that allows you to see post in a UITableView. In its Navigation Bar I have a post button that when pressed presents a UIView subclass and shows it on the top of the screen. I have an image on that UIView that when tapped I want to present the UIImagePickerController to allow users to pick an image to post to the service. How can I do this since my subview is not a view controller it cannot present the UIImagePickerController.
Below is my subview code.
#import "PostView.h"
#implementation PostView
#synthesize attachedLabel;
#synthesize postButton;
#synthesize textView;
#synthesize characterLimit;
#synthesize attachImage;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
originalFrame = frame;
NSArray *xib = [[NSBundle mainBundle] loadNibNamed:#"PostView" owner:self options:nil];
PostView *view = [xib objectAtIndex:0];
[view setBackgroundColor:[UIColor whiteColor]];
[view setAlpha:0.7f];
attachedLabel = [[UILabel alloc] initWithFrame:CGRectMake(204, 212, 56, 21)];
attachedLabel.textColor = [UIColor blackColor];
[attachedLabel setText:#"Attached"];
attachedLabel.backgroundColor = [UIColor clearColor];
attachedLabel.font = [UIFont fontWithName:text_font_name size:12.0];
characterLimit = [[UILabel alloc] initWithFrame:CGRectMake(246, 13, 50, 21)];
[characterLimit setTextAlignment:NSTextAlignmentRight];
characterLimit.textColor = [UIColor blackColor];
characterLimit.backgroundColor = [UIColor clearColor];
characterLimit.font = [UIFont fontWithName:text_font_name size:12.0];
attachImage = [[UIImageView alloc] initWithFrame:CGRectMake(270, 208, 30, 30)];
[attachImage setImage:[UIImage imageNamed:#"attachphoto30x30.png"]];
[self.textView setDelegate:self];
[self.textView setAlpha:0.7f];
[self.textView setTextColor:[UIColor whiteColor]];
[self.textView setBackgroundColor:[UIColor clearColor]];
self.layer.cornerRadius = 10.0f;
self.layer.masksToBounds = YES;
[self addSubview:view];
[self addSubview:characterLimit];
[self addSubview:attachedLabel];
[self addSubview:attachImage];
}
return self;
}
- (IBAction)openCamera:(id)sender
{
UIImagePickerController *controller = [[UIImagePickerController alloc] init];
controller.delegate = self;
//[self presentViewController:controller animated:YES completion:nil];
NSLog(#"%#", #"Image Tapped");
}
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
{
/*[picker dismissViewControllerAnimated:YES completion:nil];
UIImage *image = [info objectForKey: UIImagePickerControllerOriginalImage];
UIImage *scale = [image scaleToSize:CGSizeMake(320.0f, 548.0f)];
imageData = UIImageJPEGRepresentation(scale, 1);
encodedImage = [self Base64Encode:imageData];
[attachedLabel setHidden:NO];
*/
}
#pragma mark Custom alert methods
- (IBAction)postAction:(id)sender
{
[self hide];
}
- (void)show
{
//prepare attachImage
attachImage.userInteractionEnabled = YES;
UITapGestureRecognizer *tapAttach = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(openCamera:)];
tapAttach.numberOfTapsRequired = 1;
[self.attachImage addGestureRecognizer:tapAttach];
isShown = YES;
self.transform = CGAffineTransformMakeScale(0.1, 0.1);
self.alpha = 0;
[UIView beginAnimations:#"showAlert" context:nil];
[self setBackgroundColor:[UIColor clearColor]];
[UIView setAnimationDelegate:self];
self.transform = CGAffineTransformMakeScale(1.1, 1.1);
self.alpha = 1;
[UIView commitAnimations];
}
- (void)hide
{
isShown = NO;
[UIView beginAnimations:#"hideAlert" context:nil];
[UIView setAnimationDelegate:self];
[[NSNotificationCenter defaultCenter] postNotificationName:#"hidePostView_Notification" object:nil];
self.transform = CGAffineTransformMakeScale(0.1, 0.1);
self.alpha = 0;
[UIView commitAnimations];
}
- (void)toggle
{
if (isShown)
{
[self hide];
} else
{
[self show];
}
}
#pragma mark Animation delegate
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
if ([animationID isEqualToString:#"showAlert"])
{
if (finished)
{
[UIView beginAnimations:nil context:nil];
self.transform = CGAffineTransformMakeScale(1.0, 1.0);
[UIView commitAnimations];
}
} else if ([animationID isEqualToString:#"hideAlert"])
{
if (finished)
{
self.transform = CGAffineTransformMakeScale(1.0, 1.0);
self.frame = originalFrame;
}
}
}
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
return YES;
}
- (BOOL)textView:(UITextView *)textViewer shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)string
{
if ([string isEqualToString:#"\n"])
{
[textViewer resignFirstResponder];
}
return [self isAcceptableTextLength:textViewer.text.length + string.length - range.length];
}
-(IBAction)checkIfCorrectLength:(id)sender
{
if (![self isAcceptableTextLength:self.textView.text.length])
{
// do something to make text shorter
}
}
- (BOOL)isAcceptableTextLength:(NSUInteger)length
{
return length <= 160;
}
- (void)textViewDidChange:(UITextView *)textViewer
{
NSString *characters = [[NSString stringWithFormat:#"%d", textViewer.text.length] stringByAppendingString:#"/160"];
NSLog(#"%#", characters);
[self updateDisplay:characters];
}
-(void) updateDisplay : (NSString *)str
{
[self.characterLimit performSelectorOnMainThread : # selector(setText : ) withObject:str waitUntilDone:YES];
}
#end
Yes, you can not present a viewcontroller from a UIView subclass.
To solve this problem, you can use your subview's superview's viewcontroller class. calling [self.superview nextResponder] in your subview will return you the superview's viewcontroller. Using that you can present your UIImagePicker view controller. To use the presentViewController method, you should cast [self.superview nextResponder] to your parentviewcontroller's class type. Also make sure you import parentview controller.h inside subview.m file
[(YourParentViewController *)[self.superview nextResponder] presentViewController:controller animated:YES completion:nil];
You should present a UIViewController subclass rather than a UIView subclass.
I would also say that UIViewController should be responsible for handling data and operational logic for its views. Check out some of the docs:
View Controller Basics:
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/AboutViewControllers/AboutViewControllers.html
UIViewController Class Reference:
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/AboutViewControllers/AboutViewControllers.html
I wrote a nice gallery view controller .h .m and .xib that work fine for my purposes. Tap a programmatically created button and load an image, play a movie or view a pdf or website - while in an existing uinavigationcontroller. I want to change it so I can add the contents of the xib in code - without using the nib file. In this way it will be more useable (I think).
The problem is the functions in the .m that reference, for instance - [self presentMoviePlayerViewControllerAnimated:YES] etc do not work. I tried making a property of the rootviewcontroller in this new .h and .m and replacing self with myController (property name). But my view controller code relies on uinavigation existing to push new content or things like that. How can I remove/tweak these references to self or a reliance on uinavigationcontrollers so it will work like when it has a view controller for a nib?
Edit: Code added below. In the nib there is just a uiscrollview called uis_thumbScrollView. I would like to add this anywhere by simply calling something like:
[self.view addSubview:[[ebThumbScroller alloc] initWithFrame:CGRectMake(0, 0, 1024, 733)]];
Everyone's comments reminded me that the uiview this will be put in exists within the rootviewcontroller, over the top. Maybe this is why I can hear the movie playing - but not see it.
Note: The code creates a series of uiviews with buttons inside of a uiscrollview.
.h
#import
#import "ebAppDelegate.h"
#import "MediaPlayer/MediaPlayer.h"
#interface HomeGalleryViewController : UIViewController <UIScrollViewDelegate, UIGestureRecognizerDelegate, UIDocumentInteractionControllerDelegate> {
BOOL pageControlBeingUsed;
int buttonCount;
CGFloat _minimumColumnGap;
UIEdgeInsets _contentInsets;
NSInteger _colCount;
NSInteger _rowCount;
CGFloat _rowGap;
CGFloat _colGap;
UIEdgeInsets _effectiveInsets;
//int iGalleryThumbs;
//int iPlanThumbs;
int iTotalButtons;
ebAppDelegate *ebappdelegate;
ebGalleryItem *ebgalleryItem;
NSDictionary *gallDict;
NSArray *gallerySections;
NSArray *galleryArray;
NSMutableArray *nsm_gallArray;
UIDocumentInteractionController *controller;
}
//#property (nonatomic, retain) IBOutlet UIButton *bItem;
#property (nonatomic, retain) NSString *galleryNameString;
#property (nonatomic, retain) IBOutlet UIScrollView* scrollView;
#property (retain, nonatomic) NSMutableArray *arr_Views;
#property (strong, nonatomic) IBOutlet UIScrollView* uis_thumbScrollView;
#property (strong, nonatomic) IBOutlet UIPageControl* uis_pageControl;
#property (strong, nonatomic) IBOutlet UIView *uiv_thumbView;
#property (strong, nonatomic) MPMoviePlayerController *player;
#property (strong, nonatomic) MPMoviePlayerViewController *playerViewController;
- (IBAction)changePage;
- (IBAction) clickOpen:(id)sender;
- (void)playMovie:(NSString*)movieName;
- (void)movieFinishedCallback:(NSNotification*)_notification;
#end
.m
#import "HomeGalleryViewController.h"
#import "ebAppDelegate.h"
#import "GalleryImagesViewController.h"
#import "Gallery.h"
#import "GalleryThumbnailsViewController.h"
#import "GalleriesListViewController.h"
#import <QuartzCore/CoreAnimation.h>
#import "ebGalleryItem.h"
#import "WebViewController.h"
#implementation HomeGalleryViewController
// buttons
#define hGutter 17
#define vGutter 13
#define btnSize 130
#define topSpace 50
#define leftMargin 100
#synthesize uiv_thumbView;
#synthesize uiv_gallCat0, uiv_gallCat1, uiv_gallCat2,uiv_gallCat3, uiv_gallCat4, uiv_gallCat5,uiv_gallCat6;
#synthesize uis_thumbScrollView, uis_pageControl;
#synthesize galleryNameString,scrollView,arr_Views;
#synthesize player, playerViewController;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
ebappdelegate = (ebAppDelegate *)[[UIApplication sharedApplication] delegate];
arr_Views = [[NSMutableArray alloc] init];
self.scrollView.contentSize = CGSizeMake(1024, 1005);
// nsarray of dictionaries (galleries)
gallerySections = ebappdelegate.arr_galleryData;
NSLog(#"gallerySections count:%i",[gallerySections count]);
nsm_gallArray = [NSMutableArray arrayWithCapacity:1];
[self layoutGalleryThumbs];
}
#pragma mark
#pragma mark Layout Gallery Thumbs
-(void)layoutGalleryThumbs {
NSUInteger numGallSections = [gallerySections count];
NSLog(#"gallerySections data:%#",gallerySections);
NSLog(#"numGallSections count:%i",numGallSections);
// Window bounds.
CGRect bounds = CGRectMake(0, 0, 1024, 215);
for (int i=0; i<numGallSections; i++) {
// Create a view and add it to the window.
UIView* vview = [[UIView alloc] initWithFrame: CGRectMake(0, bounds.size.height*i-1, bounds.size.width, bounds.size.height)];
[vview setBackgroundColor: [UIColor whiteColor]];
[vview setTag:i];
//vview.backgroundColor = (UIColor (i % 2 == 0 ? cyanColor : whiteColor];
vview.backgroundColor = (i % 2 == 0)? [UIColor lightGrayColor] : [UIColor whiteColor];
[arr_Views addObject:vview];
// add line below at bottom
UIView* lineView = [[UIView alloc] initWithFrame: CGRectMake(280, bounds.size.height, 700, 2)];
[lineView setBackgroundColor: [UIColor grayColor]];
lineView.alpha = 0.5;
[vview addSubview:lineView];
[uis_thumbScrollView addSubview: vview];
NSLog(#"start===============i:%i",i);
// grab a gallery
gallDict = [gallerySections objectAtIndex:i]; // grab dict
galleryArray = [gallDict objectForKey:#"gallSectionData"]; // grab array from dict
NSLog(#"galleryArray:%#",[galleryArray description]);
NSString *secTitle = [gallDict objectForKey:#"gallSectionName"];
iTotalButtons = [galleryArray count];
NSLog(#"iTotalButtons count:%i",iTotalButtons);
_minimumColumnGap = 5;
_colCount = floorf((uis_thumbScrollView.bounds.size.width - _contentInsets.left - _contentInsets.right) / btnSize);
while (1) {
_colGap = (uis_thumbScrollView.bounds.size.width - _contentInsets.left - _contentInsets.right - btnSize * _colCount) / (_colCount + 1);
if (_colGap >= _minimumColumnGap)
break;
--_colCount;
};
_rowCount = (iTotalButtons + _colCount - 1) / _colCount;
_rowGap = _colGap;
_effectiveInsets = UIEdgeInsetsMake(_contentInsets.top + _rowGap,
_contentInsets.left + _colGap,
_contentInsets.bottom + _rowGap,
_contentInsets.right + _colGap);
NSLog(#"row count:%i",_rowCount);
NSLog(#"col count:%i",_colCount);
buttonCount=0;
for (int e=0; e<iTotalButtons; e++) {
NSLog(#"e:%i",e);
ebgalleryItem = [galleryArray objectAtIndex:e];
UIImage *thumbImg = [UIImage imageNamed:ebgalleryItem.gallThumb];
UIButton *button = [UIButton buttonWithType: UIButtonTypeCustom];
CGRect frame = CGRectMake (btnSize*e+leftMargin, topSpace,
btnSize-hGutter, btnSize-vGutter );
[button setFrame: frame];
NSLog(#"added button");
//[button setBackgroundImage:thumbImg forState:UIControlStateNormal];
[button setImage:thumbImg forState:UIControlStateNormal];
[button setTitle:ebgalleryItem.gallName forState:UIControlStateNormal];
NSLog(#"%#",button.titleLabel.text);
[button addTarget: NULL action:#selector(clickOpen:) forControlEvents:UIControlEventTouchUpInside];
UILongPressGestureRecognizer *tapAndHold = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longclickOpen:)];
[tapAndHold setMinimumPressDuration:0.33];
[button addGestureRecognizer:tapAndHold];
[button setTag:e];
//[button setTag:i*_colCount+e];
NSLog(#" button tag=%i", button.tag);
button.alpha=1.0;
[[arr_Views objectAtIndex:i] addSubview:button];
NSLog(#"middle====i:%i",i);
// caption label
CGRect labelFrame = CGRectMake( btnSize*e+leftMargin, 125,
btnSize-hGutter, btnSize-vGutter );
UILabel* label = [[UILabel alloc] initWithFrame: labelFrame];
[label setFont:[UIFont fontWithName:#"Arial" size:14]];
label.numberOfLines = 0;
[label setText:ebgalleryItem.gallCaption];
[label setTextColor: [UIColor blackColor]];
[label setTextAlignment:UITextAlignmentCenter];
[label setBackgroundColor:[UIColor clearColor]];
[[arr_Views objectAtIndex:i] addSubview: label];
NSLog(#"middle2====i:%i",i);
buttonCount++;
}
// Section Title label
CGRect titleLabelFrame = CGRectMake(btnSize,0,250,50);
UILabel* titlelabel = [[UILabel alloc] initWithFrame: titleLabelFrame];
[titlelabel setFont:[UIFont fontWithName:#"Arial" size:16]];
[titlelabel setText:secTitle];
[titlelabel setTextColor: [UIColor blackColor]];
[titlelabel setTextAlignment:UITextAlignmentLeft];
[titlelabel setBackgroundColor:[UIColor clearColor]];
[[arr_Views objectAtIndex:i] addSubview: titlelabel];
NSLog(#"end====i:%i",i);
CGFloat scrollViewHeight = 0.0f;
for (UIView* view in self.uis_thumbScrollView.subviews)
{
if (!view.hidden)
{
CGFloat y = view.frame.origin.y;
CGFloat h = view.frame.size.height;
if (y + h > scrollViewHeight)
{
scrollViewHeight = h + y;
}
}
}
[self.uis_thumbScrollView setContentSize:(CGSizeMake(self.uis_thumbScrollView.frame.size.width, scrollViewHeight+74))]; //74 is space from top in IB of scroll
}
uiv_thumbView.alpha = 1.0;
}
#pragma mark Scrollview
- (void)scrollViewDidScroll:(UIScrollView *)sender {
// Update the page when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.uis_thumbScrollView.frame.size.width;
int page = floor((self.uis_thumbScrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.uis_pageControl.currentPage = page;
// nslogs zoomsacle/bounds
CGRect visibleRect;
visibleRect.origin = uis_thumbScrollView.contentOffset;
visibleRect.size = uis_thumbScrollView.bounds.size;
float theScale = 1.0 / [uis_thumbScrollView zoomScale];
visibleRect.origin.x *= theScale;
visibleRect.origin.y *= theScale;
visibleRect.size.width *= theScale;
visibleRect.size.height *= theScale;
NSLog( #"Visible rect: %#", NSStringFromCGRect(visibleRect) );
}
- (IBAction)changePage {
// update the scroll view to the appropriate page
CGRect frame;
frame.origin.x = self.uis_thumbScrollView.frame.size.width * self.uis_pageControl.currentPage;
frame.origin.y = 0;
frame.size = self.uis_thumbScrollView.frame.size;
[self.uis_thumbScrollView scrollRectToVisible:frame animated:YES];
}
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
pageControlBeingUsed = NO;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
pageControlBeingUsed = NO;
}
//===================================================================
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft | interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[self setUiv_thumbView:nil];
}
- (void)viewDidDisappear:(BOOL)animated {
}
- (void)viewWillAppear:(BOOL)animated {
[UIApplication sharedApplication].statusBarHidden = YES;
self.view.frame = [UIScreen mainScreen].applicationFrame;
CGRect frame = self.navigationController.navigationBar.frame;
frame.origin.y = 0;
self.navigationController.navigationBar.frame = frame;
[self.navigationController setNavigationBarHidden:YES animated:animated];
self.navigationController.navigationBar.translucent = YES;
}
- (void)viewWillDisappear:(BOOL)animated {
[UIApplication sharedApplication].statusBarHidden = NO;
CGRect frame = self.navigationController.navigationBar.frame;
frame.origin.y = 20.0;
self.navigationController.navigationBar.frame = frame;
}
- (void)viewDidAppear:(BOOL)animated {
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self.navigationController setNavigationBarHidden:YES animated:animated];
[self.navigationController setToolbarHidden:YES animated:YES];
[super viewDidAppear:animated];
}
//======================================================================
-(IBAction)clickOpen:(id)sender {
UIButton *tmpBtn = (UIButton*)sender;
NSLog(#"sender tag: %i", [sender tag]);
int superviewTag = [sender superview].tag;
NSLog(#"sender superview tag: %i", superviewTag);
gallDict = [gallerySections objectAtIndex:superviewTag]; // grab dict
galleryArray = [gallDict objectForKey:#"gallSectionData"]; // grab array from dict
tmpBtn.alpha = 0.6;
ebgalleryItem = [galleryArray objectAtIndex:[sender tag]];
NSLog(#"%#",ebgalleryItem.gallType);
NSLog(#"%#",ebgalleryItem.gallName);
NSLog(#"gallDict %#",gallDict);
if ([ebgalleryItem.gallType isEqualToString:#"movie"]) {
[self playMovie:ebgalleryItem.gallFilm];
} else if ([ebgalleryItem.gallType isEqualToString:#"image"]) {
[self imageViewer:sender];
} else if ([ebgalleryItem.gallType isEqualToString:#"pdf"]) {
[self viewPDF:ebgalleryItem.gallName];
} else if ([ebgalleryItem.gallType isEqualToString:#"web"]) {
[self openWeb:ebgalleryItem.gallName];
}
}
#pragma mark
#pragma mark Open Websites
- (IBAction)openWeb:(NSString*)thisWEB {
WebViewController *webViewController = [[WebViewController alloc]
initWithNibName:#"WebViewController"
bundle:nil];
[webViewController socialButton:thisWEB];
webViewController.title = thisWEB;
[self presentModalViewController:webViewController animated:YES];
}
#pragma mark
#pragma mark Image Viewer
-(void)imageViewer:(id)sender {
UIButton *tmpBtn = (UIButton*)sender;
galleryNameString = tmpBtn.titleLabel.text;
tmpBtn.alpha = 0.6;
GalleryImagesViewController *vc = [[GalleryImagesViewController alloc] initWithGallery:[Gallery galleryNamed:galleryNameString]];
[vc goToPageAtIndex:0 animated:NO];
CATransition* transition = [CATransition animation];
transition.duration = 0.33;
transition.type = kCATransitionFade;
transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer
addAnimation:transition forKey:kCATransition];
[self.navigationController pushViewController:vc animated:NO];
}
#pragma mark
#pragma mark PDF Viewer
-(void)viewPDF:(NSString*)thisPDF {
NSString *fileToOpen = [[NSBundle mainBundle] pathForResource:thisPDF ofType:#"pdf"];
NSURL *url = [NSURL fileURLWithPath:fileToOpen];
NSLog(#"%#",fileToOpen);
controller = [UIDocumentInteractionController interactionControllerWithURL:url];
[self previewDocumentWithURL:url];
}
- (IBAction) clickClose:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
- (void)previewDocumentWithURL:(NSURL*)url
{
UIDocumentInteractionController* preview = [UIDocumentInteractionController interactionControllerWithURL:url];
preview.delegate = self;
[preview presentPreviewAnimated:YES];
}
//======================================================================
- (void)documentInteractionControllerDidDismissOptionsMenu:(UIDocumentInteractionController *)controller{
}
//===================================================================
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
{
return self;
}
- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller
{
return self.view;
}
- (CGRect)documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller
{
return self.view.frame;
}
-(IBAction)longclickOpen:(UILongPressGestureRecognizer*)gesture {
if (gesture.state == UIGestureRecognizerStateBegan ) {
[self.navigationController setNavigationBarHidden:NO];
ebAppDelegate *appDelegate = (ebAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.isFromLongPress=YES;
//NSUInteger i = [gesture.view tag];
//galleryNameString = [appDelegate.arr_galleryData objectAtIndex:i];
NSLog(#"load %#",galleryNameString);
UIButton *btn = (UIButton*)gesture.view;
galleryNameString = btn.titleLabel.text; btn.alpha = 0.6;
//NSLog(#"Long Press");
//NSLog(#"llongclickOpen");
UIViewController *vc = [[GalleryThumbnailsViewController alloc] initWithGallery:[Gallery galleryNamed:galleryNameString]];
CATransition* transition = [CATransition animation];
transition.duration = 0.33;
transition.type = kCATransitionFade;
transition.subtype = kCATransitionFromTop;
[self.navigationController.view.layer
addAnimation:transition forKey:kCATransition];
[self.navigationController pushViewController:vc animated:NO];
}
}
-(void)playMovie:(NSString*)movieName {
NSString *url = [[NSBundle mainBundle]
pathForResource:movieName
ofType:#"m4v"];
NSLog(#"%#",movieName);
playerViewController = [[MPMoviePlayerViewController alloc]
initWithContentURL:[NSURL fileURLWithPath:url]];
[[NSNotificationCenter defaultCenter] removeObserver:playerViewController
name:MPMoviePlayerPlaybackDidFinishNotification
object:playerViewController.moviePlayer];
// Register this class as an observer instead
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(movieFinishedCallback:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:playerViewController.moviePlayer];
[self.view insertSubview:playerViewController.view atIndex:50];
//---play movie---
player = [playerViewController moviePlayer];
player.controlStyle = MPMovieControlStyleFullscreen;
player.repeatMode=MPMovieRepeatModeOne;
[self presentMoviePlayerViewControllerAnimated:playerViewController];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[super viewDidLoad];
}
- (void)movieFinishedCallback:(NSNotification*)aNotification {
// Obtain the reason why the movie playback finished
NSNumber *finishReason = [[aNotification userInfo] objectForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey];
// Dismiss the view controller ONLY when the reason is not "playback ended"
if ([finishReason intValue] != MPMovieFinishReasonPlaybackEnded)
{
MPMoviePlayerController *moviePlayer = [aNotification object];
// Remove this class from the observers
[[NSNotificationCenter defaultCenter] removeObserver:self
name:MPMoviePlayerPlaybackDidFinishNotification
object:moviePlayer];
// Dismiss the view controller
[self dismissModalViewControllerAnimated:YES];
}
}
#end
If your only problem is the not working [self presentMoviePlayerViewControllerAnimated:YES] method, the problem is that presentMoviePlayerViewControllerAnimated: requires the actual moviePlayerViewController as an argument not a boolean value. (assuming you're refering to this method of the UIViewController category) UIViewController MediaPlayer Additions Reference
So if you replace that by say presentMoviePlayerViewControllerAnimated:self.moviePlayerVC, it should work as expected.
I'm not sure I understand your question, but if you need to wrap your controller to some UINavigationController you can do it like this:
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myController];
navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
navController.navigationBar.barStyle = UIBarStyleBlack;
[self presentViewController:navController animated:YES completion:^{
//
}];
later on any child controller will have the navigation hierarchy.