I have a Universal app (iPhone/iPad) which has an iAd displayed at the bottom of the view.
I use the following code to position it on view load;
- (void)viewDidLoad {
bannerIsVisible = YES;
ADBannerView *adView = [[ADBannerView alloc] initWithFrame:CGRectZero];
float origin_y;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
origin_y = 360.0;
else
origin_y = self.view.frame.size.height;
adView.frame = CGRectMake(0.0,origin_y, adView.frame.size.width, adView.frame.size.height);
adView.delegate = self;
if ( &ADBannerContentSizeIdentifierPortrait != NULL ) {
adView.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifierPortrait];
adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
else {
adView.requiredContentSizeIdentifiers = [NSSet setWithObject:ADBannerContentSizeIdentifier320x50];
adView.currentContentSizeIdentifier = ADBannerContentSizeIdentifier320x50;
}
[self.view bringSubviewToFront:adView];
[webView addSubview:adView];
[super viewDidLoad];
}
Now I want to support all 4 orienations i.e. the iAd should move to the bottom on all the 4 orienations
So my question is simply how do I update the following code to support the same;
(BOOL)shouldAutorotateToInterfaceOrientationUIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return YES;
}
Please note 2 things;
1. I need the same code to work on both iPhone/iPad
2. I am ready to update the fixed value of origin_y from 360.0 to whatever you can suggest.
Thank you.
You can work with the autoResizingMask, like this :
[adView setAutoresizingMask:UIViewAutoresizingFlexibleRightMargin
| UIViewAutoresizingFlexibleTopMargin
| UIViewAutoresizingFlexibleHeight ];
Without the UIViewAutoresizingFlexibleBottomMargin, this means that the object will keep the same margin from the bottom of the screen in every device orientation, so stay at the bottom in your case.
Related
I have a navigation controller which displays two view controllers at once. They are layered and the front most controller can be dragged down to reveal the controller below.
My app delegate is configured so the app will only allow interface orientations when the view in the back is being revealed, as seen below.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if (self.revealNavigationController.isViewRevealed)
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
return UIInterfaceOrientationMaskPortrait;
}
Naturally this causes both the front and the back view controller to rotate when the device is rotated but I am only interested in rotating the back view controller.
Is there any way to completely disable rotation in the front most view controller?
You need to use the view controller containment APIs added in iOS5. Basically, what you need to do is remove your one view controller when you no longer want it to participate in the rotation events, and add it back when its ready again. A sample would be...
#implementation AXRotationDemoViewController
- (id)init
{
if ((self = [super init]))
{
self.oneViewController = [[AXLoggingViewController alloc] init];
self.oneViewController.interfaceOrientations = UIInterfaceOrientationMaskPortrait;
self.twoViewController = [[AXLoggingViewController alloc] init];
self.twoViewController.interfaceOrientations = UIInterfaceOrientationMaskAllButUpsideDown;
}
return self;
}
- (void)viewDidLoad
{
[self.oneViewController willMoveToParentViewController:self];
[self addChildViewController:self.oneViewController];
[self.view addSubview:self.oneViewController.view];
[self.oneViewController didMoveToParentViewController:self];
[self.twoViewController willMoveToParentViewController:self];
[self addChildViewController:self.twoViewController];
[self.view addSubview:self.twoViewController.view];
[self.twoViewController didMoveToParentViewController:self];
self.oneViewController.view.backgroundColor = [UIColor redColor];
self.twoViewController.view.backgroundColor = [UIColor greenColor];
UIButton * showBackButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[showBackButton setTitle:#"Toggle Back/Front" forState:UIControlStateNormal];
[showBackButton addTarget:self action:#selector(_toggle:) forControlEvents:UIControlEventTouchUpInside];
[showBackButton sizeToFit];
showBackButton.center = self.view.center;
[self.view addSubview:showBackButton];
}
- (void)_toggle:(id)sender
{
if ([self.childViewControllers containsObject:self.oneViewController])
{
[self.oneViewController.view removeFromSuperview];
[self.oneViewController removeFromParentViewController];
}
else
{
[self.oneViewController willMoveToParentViewController:self];
[self addChildViewController:self.oneViewController];
[self.view addSubview:self.oneViewController.view];
[self.oneViewController didMoveToParentViewController:self];
UIWindow * window = self.view.window;
UIViewController * hack = window.rootViewController;
window.rootViewController = nil;
window.rootViewController = hack;
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
CGRect halfScreenFrame = self.view.bounds;
halfScreenFrame.size.height /= 2;
self.oneViewController.view.frame = halfScreenFrame;
self.twoViewController.view.frame = CGRectOffset(halfScreenFrame, 0, halfScreenFrame.size.height);
}
- (NSUInteger)supportedInterfaceOrientations
{
if ([self.childViewControllers containsObject:self.oneViewController])
return self.oneViewController.supportedInterfaceOrientations;
return self.twoViewController.supportedInterfaceOrientations;
}
#end
However you may notice, there is no official way to really tell iOS you've changed the value of supportedInterfaceOrientations, so your best bet is either a) use a hack like in my example above to force iOS to redo everything or b) don't let the user close the back view until the device is already in portrait again.
Here is the sample I put together if that doesn't explain things well enough.
Yes, take a look at the -supportedInterfaceOrientations method in UIViewController. You return a UIInterfaceOrientationMask bitmask that specifies the orientations you want that UIViewController subclass to support.
The solution suggested by axiixc is generally better so depending on your problem, you should look at his answer. However, this did not solve my problem. I had a UINavigationController in which I inserted the view of a view controller as subview at index 0. This way, the view would be in the back. I had then made the UINavigationBar draggable so that when it dragged down, it would reveal the view in the back. The front most view would then move with the navigation bar.
I did not manage to get this to work with the view controller containment API introduced iOS 5, as suggested by axiixc.
Instead, I removed the view from the navigation controller and added it directly to the UIWindow when the app was launched and I handled the rotation of this view myself and disabled rotation on all other views (that is, I disabled it on the navigation controller).
This is how I added the view in -application:didFinishLaunchingWithOptions:
self.revealViewController = [[RevealViewController alloc] init];
[self.window insertSubview:self.revealViewController.view atIndex:0];
Then, right after that I registered for UIDeviceOrientationDidChangeNotification.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
My didRotate: looks like this: (this is inspired by another answer on StackOverflow which I am now unable to find again, sorry)
- (void)didRotate:(NSNotification *)notification
{
// Only rotate if the view is revealed
if (self.revealNavigationController.isViewRevealed)
{
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
[self updateForDeviceOrientation:orientation animated:YES];
}
}
I call -updateForDeviceOrientation:animated:
- (void)updateForDeviceOrientation:(UIDeviceOrientation)orientation animated:(BOOL)animated
{
CGFloat degrees = 0.0f;
switch (orientation)
{
case UIDeviceOrientationLandscapeLeft:
degrees = 90.0f;
break;
case UIDeviceOrientationLandscapeRight:
degrees = -90.0f;
break;
case UIDeviceOrientationPortrait:
degrees = 0.0f;
break;
default:
break;
}
CGFloat duration = (animated) ? [UIApplication sharedApplication].statusBarOrientationAnimationDuration : 0.0f;
__weak typeof(self) weakSelf = self;
[UIView animateWithDuration:duration animations:^{
// Rotate view
weakSelf.revealViewController.view.transform = CGAffineTransformIdentity;
weakSelf.revealViewController.view.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(degrees));
// Resize view for rotation
CGFloat width, height;
if (UIDeviceOrientationIsLandscape(orientation))
{
width = MAX(CGRectGetWidth(weakSelf.revealViewController.view.bounds), CGRectGetHeight(weakSelf.revealViewController.view.bounds));
height = MIN(CGRectGetWidth(weakSelf.revealViewController.view.bounds), CGRectGetHeight(weakSelf.revealViewController.view.bounds));
}
else
{
width = MIN(CGRectGetWidth(weakSelf.revealViewController.view.bounds), CGRectGetHeight(weakSelf.revealViewController.view.bounds));
height = MAX(CGRectGetWidth(weakSelf.revealViewController.view.bounds), CGRectGetHeight(weakSelf.revealViewController.view.bounds));
}
CGSize newSize = CGSizeMake(width, height);
CGRect viewBounds = weakSelf.revealViewController.view.bounds;
viewBounds.size = newSize;
weakSelf.revealViewController.view.bounds = viewBounds;
CGRect viewFrame = weakSelf.revealViewController.view.frame;
viewFrame.size = newSize;
weakSelf.revealViewController.view.bounds = viewFrame;
}];
}
I look at some examples at Github, but all of them were without storyboard usage.
I tried to use that code in my app, but all I see on external device in simulator is black screen.
Code I have now:
if([[UIScreen screens]count] > 1) {
CGSize maxSize;
UIScreenMode *maxScreenMode;
for(int i = 0; i < [[[[UIScreen screens] objectAtIndex:1] availableModes]count]; i++)
{
UIScreenMode *current = [[[[UIScreen screens]objectAtIndex:1]availableModes]objectAtIndex:i];
if(current.size.width > maxSize.width)
{
maxSize = current.size;
maxScreenMode = current;
}
}
UIScreen *externalScreen = [[UIScreen screens] objectAtIndex:1];
externalScreen.currentMode = maxScreenMode;
[self myScreenInit:externalScreen];
}
- (void) screenDidConnect:(NSNotification *)notification {
[self myScreenInit:[notification object]];
}
- (void) myScreenInit:(UIScreen *)connectedScreen {
CGRect frame = connectedScreen.bounds;
UIWindow *window = [[UIWindow alloc] initWithFrame:frame];
window.backgroundColor = [UIColor whiteColor];
[window setScreen:connectedScreen];
window.hidden = NO;
}
If you want to see more than a black screen you'll need to put in some content. One option would be to add something like this:
UIView *myCustomUIView = [[MyCustomUIView alloc] initWithFrame:frame];
[window addSubview:myCustomUIView];
Then draw stuff in the view's drawRect:(CGRect) method.
Hope this helps.
I am trying to duplicate the Photos app on the iPhone. Meaning, a scrollview with multiple images, and each image can be pinched to zoom in/out.
The Apple ScrollViewSuite example code only deals with 1 image inside of a scrollview. I have found that with multiple images, scrolling through the images becomes unpredictable. Also, the view becomes uncentered after pinching to zoom.
I have found this on Stack Overflow: Zoom UIScrollView with multiple images
However, what am I supposed to write in the scrollview delegate functions?
This is what I found to work. Supports multiple images with paging and zooming. Enjoy!
#define VIEW_FOR_ZOOM_TAG (1)
#implementation SVViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIScrollView *mainScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
mainScrollView.pagingEnabled = YES;
mainScrollView.showsHorizontalScrollIndicator = NO;
mainScrollView.showsVerticalScrollIndicator = NO;
CGRect innerScrollFrame = mainScrollView.bounds;
for (NSInteger i = 0; i < 3; i++) {
UIImageView *imageForZooming = [[UIImageView alloc] initWithImage:[UIImage imageNamed:
[NSString stringWithFormat:#"page%d", i + 1]]];
imageForZooming.tag = VIEW_FOR_ZOOM_TAG;
UIScrollView *pageScrollView = [[UIScrollView alloc] initWithFrame:innerScrollFrame];
pageScrollView.minimumZoomScale = 1.0f;
pageScrollView.maximumZoomScale = 2.0f;
pageScrollView.zoomScale = 1.0f;
pageScrollView.contentSize = imageForZooming.bounds.size;
pageScrollView.delegate = self;
pageScrollView.showsHorizontalScrollIndicator = NO;
pageScrollView.showsVerticalScrollIndicator = NO;
[pageScrollView addSubview:imageForZooming];
[mainScrollView addSubview:pageScrollView];
if (i < 2) {
innerScrollFrame.origin.x += innerScrollFrame.size.width;
}
}
mainScrollView.contentSize = CGSizeMake(innerScrollFrame.origin.x +
innerScrollFrame.size.width, mainScrollView.bounds.size.height);
[self.view addSubview:mainScrollView];
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return [scrollView viewWithTag:VIEW_FOR_ZOOM_TAG];
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotate {
return NO;
}
#end
I'm creating an UIView with a label inside AppDelegate and displaying it like this:
[window addSubview:self.roundedCornerView];
Problem is when I rotate the device the view with label don't rotate at all. The text in the label is in wrong orientation as well. Window in my application got another subview which is the UIViewControllers subview and it is rotating fine.
Do I need to create another UIViewController in my AppDelegate and attach created view to it, then subclassing it and allowing for interface orientation in order to get roundedCornerView to rotate?
UPDATE
Ok I've tried to do this by creating new ViewController and sublcassing it here is code in my AppDelegate:
ActivityIndicatorWithLabelViewController *aiWithLabel = [[[ActivityIndicatorWithLabelViewController alloc] init] autorelease];
aiWithLabel.textOfTheLabel = text;
[window addSubview:aiWithLabel.view];
The ActivityIndicatorWithLabelViewController class is visible here:
//
// ActivityIndicatorWithLabelViewController.m
// LOFT
//
// Created by Marcin Zyga on 15.11.2011.
// Copyright (c) 2011 __MyCompanyName__. All rights reserved.
//
#import "ActivityIndicatorWithLabelViewController.h"
#implementation ActivityIndicatorWithLabelViewController
#synthesize roundedCornerView;
#synthesize textActivityIndicatorLabel;
#synthesize textOfTheLabel;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (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.
}
#pragma mark - View lifecycle
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
UIActivityIndicatorView *mainApplicationActivityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
mainApplicationActivityIndicatorView.frame = CGRectMake(80, 80, 40, 40);
mainApplicationActivityIndicatorView.hidesWhenStopped = YES;
//self.roundedCornerView = [[[UIView alloc] initWithFrame:CGRectMake(280, 400, 200, 200)] autorelease];
self.roundedCornerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)] autorelease];
roundedCornerView.backgroundColor = [UIColor blackColor];
roundedCornerView.alpha = 0.9f;
roundedCornerView.layer.cornerRadius = 12.0;
[roundedCornerView addSubview:mainApplicationActivityIndicatorView];
[mainApplicationActivityIndicatorView startAnimating];
// self.roundedCornerView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
//self.roundedCornerView.autoresizesSubviews = YES;
self.textActivityIndicatorLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 150, 200, 50)];
self.textActivityIndicatorLabel.backgroundColor = [UIColor clearColor];
self.textActivityIndicatorLabel.textAlignment = UITextAlignmentCenter;
self.textActivityIndicatorLabel.textColor = [UIColor whiteColor];
self.textActivityIndicatorLabel.font = [UIFont systemFontOfSize:22];
self.textActivityIndicatorLabel.text = #"";
// self.textActivityIndicatorLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
[self.roundedCornerView addSubview:textActivityIndicatorLabel];
self.textActivityIndicatorLabel.text = textOfTheLabel;
self.view.frame = CGRectMake(280, 400, 200, 200);
[self.view addSubview:self.roundedCornerView];
//self.view = self.roundedCornerView;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
[self.textActivityIndicatorLabel removeFromSuperview];
[self.textActivityIndicatorLabel release];
self.textActivityIndicatorLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
self.textActivityIndicatorLabel.backgroundColor = [UIColor clearColor];
self.textActivityIndicatorLabel.textAlignment = UITextAlignmentCenter;
self.textActivityIndicatorLabel.textColor = [UIColor whiteColor];
self.textActivityIndicatorLabel.font = [UIFont systemFontOfSize:22];
self.textActivityIndicatorLabel.text = #"Landscape";
[self.roundedCornerView addSubview:textActivityIndicatorLabel];
NSLog(#"LANDSCAPE");
}
NSLog(#"ENTERING SUPPORTED ORIENTATION!");
return YES;
}
#end
As you see there is some debug code in here. When I'm rotating the device from potrait to landscape I get ENTERING SUPPORTE ORIENTATION! as well as LADNSCAPE NSLog. Removing label is working fine, but when I'm adding new one it is still presented (the text) in wrong orientation. What I am doing wrong?
UIWindow should only have one subview which defines the root UIViewController. I believe that UIWindow only forwards rotation events to its first subview.
Create a single container UIView and move your subviews into it.
Solution is follow below steps :
In subView's .m file add code on top of interface of you view:
typedef NS_OPTIONS(NSUInteger, AGInterfaceOrientationMask) {
AGInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
AGInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
AGInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
AGInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
AGInterfaceOrientationMaskLandscape = (AGInterfaceOrientationMaskLandscapeLeft | AGInterfaceOrientationMaskLandscapeRight),
AGInterfaceOrientationMaskAll = (AGInterfaceOrientationMaskPortrait | AGInterfaceOrientationMaskLandscapeLeft | AGInterfaceOrientationMaskLandscapeRight | AGInterfaceOrientationMaskPortraitUpsideDown),
AGInterfaceOrientationMaskAllButUpsideDown = (AGInterfaceOrientationMaskPortrait | AGInterfaceOrientationMaskLandscapeLeft | AGInterfaceOrientationMaskLandscapeRight),
}
In subView's .m file add code
#pragma mark - Orientation
- (void)statusBarFrameOrOrientationChanged:(NSNotification *)notification
{
/*
This notification is most likely triggered inside an animation block,
therefore no animation is needed to perform this nice transition.
*/
[self rotateAccordingToStatusBarOrientationAndSupportedOrientations];
}
- (void)rotateAccordingToStatusBarOrientationAndSupportedOrientations
{
UIInterfaceOrientation orientation = [self desiredOrientation];
CGFloat angle = [self UIInterfaceOrientationAngleOfOrientation:orientation];
CGFloat statusBarHeight = [[self class] getStatusBarHeight];
UIInterfaceOrientation statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation;
CGAffineTransform transform = CGAffineTransformMakeRotation(angle);
CGRect frame = [[self class] rectInWindowBounds:self.view.window.bounds statusBarOrientation:statusBarOrientation statusBarHeight:statusBarHeight];
[self setIfNotEqualTransform:transform frame:frame];
CGRect rect = btnClose.frame;
rect.origin.x = (subView.frame.origin.x+subView.frame.size.width)-(rect.size.width/2);
rect.origin.y = subView.frame.origin.y-(rect.size.height/2);
btnClose.frame = rect;
}
- (void)setIfNotEqualTransform:(CGAffineTransform)transform frame:(CGRect)frame
{
if(!CGAffineTransformEqualToTransform(self.view.transform, transform))
{
self.view.transform = transform;
}
if(!CGRectEqualToRect(self.view.frame, frame))
{
self.view.frame = frame;
}
}
+ (CGFloat)getStatusBarHeight
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if(UIInterfaceOrientationIsLandscape(orientation))
{
return [UIApplication sharedApplication].statusBarFrame.size.width;
}
else
{
return [UIApplication sharedApplication].statusBarFrame.size.height;
}
}
static BOOL IS_BELOW_IOS_7()
{
static BOOL answer;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
answer = [[[UIDevice currentDevice] systemVersion] floatValue] < 7.0;
});
return answer;
}
+ (CGRect)rectInWindowBounds:(CGRect)windowBounds statusBarOrientation:(UIInterfaceOrientation)statusBarOrientation statusBarHeight:(CGFloat)statusBarHeight
{
CGRect frame = windowBounds;
if(IS_BELOW_IOS_7())
{
frame.origin.x += statusBarOrientation == UIInterfaceOrientationLandscapeLeft ? statusBarHeight : 0;
frame.origin.y += statusBarOrientation == UIInterfaceOrientationPortrait ? statusBarHeight : 0;
frame.size.width -= UIInterfaceOrientationIsLandscape(statusBarOrientation) ? statusBarHeight : 0;
frame.size.height -= UIInterfaceOrientationIsPortrait(statusBarOrientation) ? statusBarHeight : 0;
}
return frame;
}
- (UIInterfaceOrientation)desiredOrientation
{
UIInterfaceOrientation statusBarOrientation = [[UIApplication sharedApplication] statusBarOrientation];
AGInterfaceOrientationMask statusBarOrientationAsMask = [self AGInterfaceOrientationMaskFromOrientation:statusBarOrientation];
if(self.supportedInterfaceOrientations & statusBarOrientationAsMask)
{
return statusBarOrientation;
}
else
{
if(self.supportedInterfaceOrientations & AGInterfaceOrientationMaskPortrait)
{
return UIInterfaceOrientationPortrait;
}
else if(self.supportedInterfaceOrientations & AGInterfaceOrientationMaskLandscapeLeft)
{
return UIInterfaceOrientationLandscapeLeft;
}
else if(self.supportedInterfaceOrientations & AGInterfaceOrientationMaskLandscapeRight)
{
return UIInterfaceOrientationLandscapeRight;
}
else
{
return UIInterfaceOrientationPortraitUpsideDown;
}
}
}
-(CGFloat)UIInterfaceOrientationAngleOfOrientation:(UIInterfaceOrientation)orientation
{
CGFloat angle;
switch (orientation)
{
case UIInterfaceOrientationPortraitUpsideDown:
angle = M_PI;
break;
case UIInterfaceOrientationLandscapeLeft:
angle = -M_PI_2;
break;
case UIInterfaceOrientationLandscapeRight:
angle = M_PI_2;
break;
default:
angle = 0.0;
break;
}
return angle;
}
-(AGInterfaceOrientationMask)AGInterfaceOrientationMaskFromOrientation:(UIInterfaceOrientation)orientation
{
return 1 << orientation;
}
//If dealloc is a duplicate method then remove this dealloc method and add the unregisterFromNotifications method in dealloc.
- (void)dealloc {
[self unregisterFromNotifications];
}
-(void)unregisterFromNotifications
{
//for orientation
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidChangeStatusBarFrameNotification object:nil];
}
Also In subView's .h file add this line.
- (void)rotateAccordingToStatusBarOrientationAndSupportedOrientations;
Now time to use above added code for orientation change in subview.
While adding subview in window or self.view like this :
[objAppDelegate.window addSubview:objViewController.view];
//added this method to rotate subview according to orientation when added
[objViewController rotateAccordingToStatusBarOrientationAndSupportedOrientations];
Reference taken from AGWindowView
Window subviews don't rotate by themselves, they usually rotate with the help of a view controller.
You could either add the views you want rotated to a view controller and then add that to the window, or you could register for device orientation changes notifications and rotate them yourself.
I am trying to display a modal view controller as a UIPresentationFormSheet. The view appears, but I can't seem to resize it. My XIB has the proper height & width, but it seems to get overridden when I call it like this:
composeTweetController = [[ComposeTweet alloc] initWithNibName:#"ComposeTweet" bundle:nil];
composeTweetController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:composeTweetController animated:TRUE];
Any thoughts? I am using the iPhone SDK 3.2 beta 4
You are able to adjust the frame of a modal view after presenting it:
Tested in iOS 5.1 - 7.1
MyModalViewController *targetController = [[[MyModalViewController alloc] init] autorelease];
targetController.modalPresentationStyle = UIModalPresentationFormSheet;
targetController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; //transition shouldn't matter
[self presentViewController:targetController animated:YES completion:nil];
if(floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1){
targetController.view.superview.frame = CGRectInset(targetController.view.superview.frame, 100, 50);
}else{
targetController.view.frame = CGRectInset(targetController.view.frame, 100, 50);
targetController.view.superview.backgroundColor = [UIColor clearColor];
}
Here's a method that works on iOS7 as well as iOS5 and iOS6: (arc)
-(void)presentController:(UIViewController*)controller fromRootController:(UIViewController*)rootController withSize:(CGSize)size
{
UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:controller];
nav.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
nav.modalPresentationStyle = UIModalPresentationFormSheet;
[rootController presentModalViewController:nav animated:YES];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
{
nav.view.superview.backgroundColor = [UIColor clearColor];
nav.view.bounds = CGRectMake(0, 0, size.width, size.height);
}
else
{
nav.view.superview.bounds = CGRectMake(0, 0, size.width, size.height);
}
}
composeTweetController = [[ComposeTweet alloc] initWithNibName:#"ComposeTweet" bundle:nil];
composeTweetController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:composeTweetController animated:TRUE];
//if you want to change its size but the view will remain centerd on the screen in both portrait and landscape then:
composeTweetViewController.view.superview.bounds = CGRectMake(0, 0, 320, 480);
//or if you want to change it's position also, then:
composeTweetViewController.view.superview.frame = CGRectMake(0, 0, 320, 480);
As of iOS7 you can simply do
composeTweetController.preferredContentSize = CGSizeMake(380.0, 550.0);
Tested and works for iOS 6, using XCode 4.5
I stumbled upon my answer after reading much of the tips on here:
In the viewWillAppear:(BOOL)animated method:
[super viewWillAppear:animated];
//resize modal view
self.view.superview.bounds = CGRectMake(0, 0, 432, 680);
In the viewDidAppear:(BOOL)animated method:
CGPoint centerPoint = CGPointMake([[UIScreen mainScreen] bounds].size.width/2, [[UIScreen mainScreen] bounds].size.height/2);
self.view.superview.center = centerPoint;
I tried to add the centering code in the same place as the resizing code, but that did not work. For some reason, it only works after the view has appeared on the screen.
I surmise that it has something to do with the way that UIModalPresentationFormSheet works, because when I was stepping through in the LLDB debugger, I noticed that there was a variable _formSheetSize that was still {540, 620}. Go figure.
This will work with any UIModalTransitionStyle
#interface BaseDialog ()
#property(nonatomic,assign) CGRect origFrame;
#end
#implementation BaseDialog
-(void)viewDidLoad{
[super viewDidLoad];
self.origFrame=self.view.frame;
}
-(CGSize)formSheetSize{
return self.origFrame.size;
}
Following first code is how to present your model view controller
composeTweetController = [[ComposeTweet alloc] initWithNibName:#"ComposeTweet" bundle:nil];
composeTweetController.modalPresentationStyle = UIModalPresentationFormSheet;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:composeTweetController];
navigationController.delegate = self;
[self presentModalViewController:navigationController animated:YES];
And In your ComposeTweet controller class
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.view.superview.frame = CGRectMake(0, 0,500,400);
}
iOS 7
So the approach of setting the superview's frame or bounds doesn't work anymore on iOS 7 (for UIModalTransitionStyleCoverVertical). You can, however, now set the background color of the superview to clear and then change the frame of the modal view controller how you see fit.
So in iOS 7 you will want to:
present the view controller (presentation mode: UIModalPresentationFormSheet)
set view controller superview background color to clear
change frame of view controller as desired (perhaps making it smaller and then centering it in superview)
I got a full screen modal view from UIPresentationFormSheet with just this line:
modalViewController.view.superview.bounds = CGRectMake(0, 0, 1024, 748);
#bdrobert sadly your nice solution does not work anymore on iOS6 - the container keeps the original size even though the new viewcontroller is embedded with the custom size.
You probably need to use the containment API introduced in iOS5, but you need to add a dimmed background on your own, fetching all touch events for that area.
On change of orientation, this code work perfect....
settingViewController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:settingViewController animated:YES completion:nil];
settingViewController.view.superview.frame = CGRectMake(0, 0, 700, 700);
UIInterfaceOrientation currentOrientation = [self getDeviceOrientation];
if(currentOrientation == UIInterfaceOrientationPortrait || currentOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
CGPoint centerPoint = CGPointMake([[UIScreen mainScreen] bounds].size.width/2, [[UIScreen mainScreen] bounds].size.height/2);
settingViewController.view.superview.center = centerPoint;
}
else
{
CGPoint centerPoint = CGPointMake([[UIScreen mainScreen] bounds].size.height/2, [[UIScreen mainScreen] bounds].size.width/2);
settingViewController.view.superview.center = centerPoint;
}
The modern ios13 way:
use popover (formsheet and page ignore preferredContentSize)
then set or override preferredContentSize aka Ed Pilowat & Co
The view size is fixed. You will have to implement things yourself if you want something different.