Window subview not rotating after orientation of the device changes - iphone

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.

Related

Prevent some view controller in a navigation controller from rotating

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;
}];
}

UIScrollview with multiple images and pinch to zoom

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

Fitting an Image to Screen on Rotation iPhone / iPad?

I have been playing around with one of the iPhone examples from Apple' web site (ScrollViewSuite) . I am trying to tweak it a bit so that when I rotate the the iPad the image will fit into the screen in landscape mode vertical. I have been successful in getting the image to rotate, but the image is larger than the height of the landscape screen, so the bottom is below the screen. I would like to image to scale to the height of the landscape screen.
I have been playing around with various autoSizingMask attributes without success.
The imageView is called "zoomView" this is the actual image which loads into a scrollView called imageScrollView.
I am trying to achieve the screen to rotate and look like this.... sorry only 1 link allowed new user :(
olsonvox.com/photos/correct.png
However, this is what My screen is looking like.
http://www.olsonvox.com/photos/incorrect.png
I would really appreciate some advice or guidance. Below is the RootViewController.m for the project.
Blade
#
import "RootViewController.h"
#define ZOOM_VIEW_TAG 100
#define ZOOM_STEP 1.5
#define THUMB_HEIGHT 150
#define THUMB_V_PADDING 25
#define THUMB_H_PADDING 25
#define CREDIT_LABEL_HEIGHT 25
#define AUTOSCROLL_THRESHOLD 30
#interface RootViewController (ViewHandlingMethods)
- (void)toggleThumbView;
- (void)pickImageNamed:(NSString *)name;
- (NSArray *)imageNames;
- (void)createThumbScrollViewIfNecessary;
- (void)createSlideUpViewIfNecessary;
#end
#interface RootViewController (AutoscrollingMethods)
- (void)maybeAutoscrollForThumb:(ThumbImageView *)thumb;
- (void)autoscrollTimerFired:(NSTimer *)timer;
- (void)legalizeAutoscrollDistance;
- (float)autoscrollDistanceForProximityToEdge:(float)proximity;
#end
#interface RootViewController (UtilityMethods)
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center;
#end
#implementation RootViewController
- (void)loadView {
[super loadView];
imageScrollView = [[UIScrollView alloc] initWithFrame:[[self view]bounds]];
// this code makes the image resize to the width and height properly.
imageScrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin| UIViewAutoresizingFlexibleBottomMargin| UIViewAutoresizingFlexibleBottomMargin;
// TRY SETTNG CENTER HERE SOMEHOW>....
[imageScrollView setBackgroundColor:[UIColor blackColor]];
[imageScrollView setDelegate:self];
[imageScrollView setBouncesZoom:YES];
[[self view] addSubview:imageScrollView];
[self toggleThumbView];
// intitializes with the first image.
[self pickImageNamed:#"lookbook1"];
}
- (void)dealloc {
[imageScrollView release];
[slideUpView release];
[thumbScrollView release];
[super dealloc];
}
#pragma mark UIScrollViewDelegate methods
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
UIView *view = nil;
if (scrollView == imageScrollView) {
view = [imageScrollView viewWithTag:ZOOM_VIEW_TAG];
}
return view;
}
/************************************** NOTE **************************************/
/* The following delegate method works around a known bug in zoomToRect:animated: */
/* In the next release after 3.0 this workaround will no longer be necessary */
/**********************************************************************************/
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
[scrollView setZoomScale:scale+0.01 animated:NO];
[scrollView setZoomScale:scale animated:NO];
}
#pragma mark TapDetectingImageViewDelegate methods
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotSingleTapAtPoint:(CGPoint)tapPoint {
// Single tap shows or hides drawer of thumbnails.
[self toggleThumbView];
}
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotDoubleTapAtPoint:(CGPoint)tapPoint {
// double tap zooms in
float newScale = [imageScrollView zoomScale] * ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:tapPoint];
[imageScrollView zoomToRect:zoomRect animated:YES];
}
- (void)tapDetectingImageView:(TapDetectingImageView *)view gotTwoFingerTapAtPoint:(CGPoint)tapPoint {
// two-finger tap zooms out
float newScale = [imageScrollView zoomScale] / ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:tapPoint];
[imageScrollView zoomToRect:zoomRect animated:YES];
}
#pragma mark ThumbImageViewDelegate methods
- (void)thumbImageViewWasTapped:(ThumbImageView *)tiv {
[self pickImageNamed:[tiv imageName]];
[self toggleThumbView];
}
- (void)thumbImageViewStartedTracking:(ThumbImageView *)tiv {
[thumbScrollView bringSubviewToFront:tiv];
}
// CONTROLS DRAGGING AND DROPPING THUMBNAILS...
- (void)thumbImageViewMoved:(ThumbImageView *)draggingThumb {
// check if we've moved close enough to an edge to autoscroll, or far enough away to stop autoscrolling
[self maybeAutoscrollForThumb:draggingThumb];
/* The rest of this method handles the reordering of thumbnails in the thumbScrollView. See */
/* ThumbImageView.h and ThumbImageView.m for more information about how this works. */
// we'll reorder only if the thumb is overlapping the scroll view
if (CGRectIntersectsRect([draggingThumb frame], [thumbScrollView bounds])) {
BOOL draggingRight = [draggingThumb frame].origin.x > [draggingThumb home].origin.x ? YES : NO;
/* we're going to shift over all the thumbs who live between the home of the moving thumb */
/* and the current touch location. A thumb counts as living in this area if the midpoint */
/* of its home is contained in the area. */
NSMutableArray *thumbsToShift = [[NSMutableArray alloc] init];
// get the touch location in the coordinate system of the scroll view
CGPoint touchLocation = [draggingThumb convertPoint:[draggingThumb touchLocation] toView:thumbScrollView];
// calculate minimum and maximum boundaries of the affected area
float minX = draggingRight ? CGRectGetMaxX([draggingThumb home]) : touchLocation.x;
float maxX = draggingRight ? touchLocation.x : CGRectGetMinX([draggingThumb home]);
// iterate through thumbnails and see which ones need to move over
for (ThumbImageView *thumb in [thumbScrollView subviews]) {
// skip the thumb being dragged
if (thumb == draggingThumb) continue;
// skip non-thumb subviews of the scroll view (such as the scroll indicators)
if (! [thumb isMemberOfClass:[ThumbImageView class]]) continue;
float thumbMidpoint = CGRectGetMidX([thumb home]);
if (thumbMidpoint >= minX && thumbMidpoint <= maxX) {
[thumbsToShift addObject:thumb];
}
}
// shift over the other thumbs to make room for the dragging thumb. (if we're dragging right, they shift to the left)
float otherThumbShift = ([draggingThumb home].size.width + THUMB_H_PADDING) * (draggingRight ? -1 : 1);
// as we shift over the other thumbs, we'll calculate how much the dragging thumb's home is going to move
float draggingThumbShift = 0.0;
// send each of the shifting thumbs to its new home
for (ThumbImageView *otherThumb in thumbsToShift) {
CGRect home = [otherThumb home];
home.origin.x += otherThumbShift;
[otherThumb setHome:home];
[otherThumb goHome];
draggingThumbShift += ([otherThumb frame].size.width + THUMB_H_PADDING) * (draggingRight ? 1 : -1);
}
// change the home of the dragging thumb, but don't send it there because it's still being dragged
CGRect home = [draggingThumb home];
home.origin.x += draggingThumbShift;
[draggingThumb setHome:home];
}
}
- (void)thumbImageViewStoppedTracking:(ThumbImageView *)tiv {
// if the user lets go of the thumb image view, stop autoscrolling
[autoscrollTimer invalidate];
autoscrollTimer = nil;
}
#pragma mark Autoscrolling methods
- (void)maybeAutoscrollForThumb:(ThumbImageView *)thumb {
autoscrollDistance = 0;
// only autoscroll if the thumb is overlapping the thumbScrollView
if (CGRectIntersectsRect([thumb frame], [thumbScrollView bounds])) {
CGPoint touchLocation = [thumb convertPoint:[thumb touchLocation] toView:thumbScrollView];
float distanceFromLeftEdge = touchLocation.x - CGRectGetMinX([thumbScrollView bounds]);
float distanceFromRightEdge = CGRectGetMaxX([thumbScrollView bounds]) - touchLocation.x;
if (distanceFromLeftEdge < AUTOSCROLL_THRESHOLD) {
autoscrollDistance = [self autoscrollDistanceForProximityToEdge:distanceFromLeftEdge] * -1; // if scrolling left, distance is negative
} else if (distanceFromRightEdge < AUTOSCROLL_THRESHOLD) {
autoscrollDistance = [self autoscrollDistanceForProximityToEdge:distanceFromRightEdge];
}
}
// if no autoscrolling, stop and clear timer
if (autoscrollDistance == 0) {
[autoscrollTimer invalidate];
autoscrollTimer = nil;
}
// otherwise create and start timer (if we don't already have a timer going)
else if (autoscrollTimer == nil) {
autoscrollTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 60.0)
target:self
selector:#selector(autoscrollTimerFired:)
userInfo:thumb
repeats:YES];
}
}
- (float)autoscrollDistanceForProximityToEdge:(float)proximity {
// the scroll distance grows as the proximity to the edge decreases, so that moving the thumb
// further over results in faster scrolling.
return ceilf((AUTOSCROLL_THRESHOLD - proximity) / 5.0);
}
- (void)legalizeAutoscrollDistance {
// makes sure the autoscroll distance won't result in scrolling past the content of the scroll view
float minimumLegalDistance = [thumbScrollView contentOffset].x * -1;
float maximumLegalDistance = [thumbScrollView contentSize].width - ([thumbScrollView frame].size.width + [thumbScrollView contentOffset].x);
autoscrollDistance = MAX(autoscrollDistance, minimumLegalDistance);
autoscrollDistance = MIN(autoscrollDistance, maximumLegalDistance);
}
- (void)autoscrollTimerFired:(NSTimer*)timer {
[self legalizeAutoscrollDistance];
// autoscroll by changing content offset
CGPoint contentOffset = [thumbScrollView contentOffset];
contentOffset.x += autoscrollDistance;
[thumbScrollView setContentOffset:contentOffset];
// adjust thumb position so it appears to stay still
ThumbImageView *thumb = (ThumbImageView *)[timer userInfo];
[thumb moveByOffset:CGPointMake(autoscrollDistance, 0)];
}
#pragma mark View handling methods
- (void)toggleThumbView {
[self createSlideUpViewIfNecessary]; // no-op if slideUpView has already been created
CGRect frame = [slideUpView frame];
if (thumbViewShowing) {
frame.origin.y = 0;
} else {
frame.origin.y = -225;
}
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[slideUpView setFrame:frame];
[UIView commitAnimations];
thumbViewShowing = !thumbViewShowing;
}
- (void)pickImageNamed:(NSString *)name {
// first remove previous image view, if any
[[imageScrollView viewWithTag:ZOOM_VIEW_TAG] removeFromSuperview];
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:#"%#.jpg", name]];
TapDetectingImageView *zoomView = [[TapDetectingImageView alloc] initWithImage:image];
zoomView.autoresizingMask = UIViewAutoresizingFlexibleWidth ;
[zoomView setDelegate:self];
[zoomView setTag:ZOOM_VIEW_TAG];
[imageScrollView addSubview:zoomView];
[imageScrollView setContentSize:[zoomView frame].size];
[zoomView release];
// choose minimum scale so image width fits screen
float minScale = [imageScrollView frame].size.width / [zoomView frame].size.width;
[imageScrollView setMinimumZoomScale:minScale];
[imageScrollView setZoomScale:minScale];
[imageScrollView setContentOffset:CGPointZero];
}
- (NSArray *)imageNames {
// the filenames are stored in a plist in the app bundle, so create array by reading this plist
NSString *path = [[NSBundle mainBundle] pathForResource:#"Images" ofType:#"plist"];
NSData *plistData = [NSData dataWithContentsOfFile:path];
NSString *error; NSPropertyListFormat format;
NSArray *imageNames = [NSPropertyListSerialization propertyListFromData:plistData
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:&error];
if (!imageNames) {
NSLog(#"Failed to read image names. Error: %#", error);
[error release];
}
return imageNames;
}
- (void)createSlideUpViewIfNecessary {
if (!slideUpView) {
[self createThumbScrollViewIfNecessary];
CGRect bounds = [[self view] bounds];
float thumbHeight = [thumbScrollView frame].size.height;
float labelHeight = CREDIT_LABEL_HEIGHT;
// create label giving credit for images
UILabel *creditLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, thumbHeight, bounds.size.width, labelHeight)];
[creditLabel setBackgroundColor:[UIColor clearColor]];
[creditLabel setTextColor:[UIColor whiteColor]];
// [creditLabel setFont:[UIFont fontWithName:#"Helvetica" size:16]];
// [creditLabel setText:#"SAMPLE TEXT"];
[creditLabel setTextAlignment:UITextAlignmentCenter];
// create container view that will hold scroll view and label
CGRect frame = CGRectMake(0.0, -225.00, bounds.size.width+256, thumbHeight + labelHeight);
slideUpView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
slideUpView = [[UIView alloc] initWithFrame:frame];
[slideUpView setBackgroundColor:[UIColor blackColor]];
[slideUpView setOpaque:NO];
[slideUpView setAlpha:.75];
[[self view] addSubview:slideUpView];
// add subviews to container view
[slideUpView addSubview:thumbScrollView];
[slideUpView addSubview:creditLabel];
[creditLabel release];
}
}
- (void)createThumbScrollViewIfNecessary {
if (!thumbScrollView) {
float scrollViewHeight = THUMB_HEIGHT + THUMB_V_PADDING;
float scrollViewWidth = [[self view] bounds].size.width;
thumbScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, scrollViewWidth, scrollViewHeight)];
[thumbScrollView setCanCancelContentTouches:NO];
[thumbScrollView setClipsToBounds:NO];
// now place all the thumb views as subviews of the scroll view
// and in the course of doing so calculate the content width
float xPosition = THUMB_H_PADDING;
for (NSString *name in [self imageNames]) {
UIImage *thumbImage = [UIImage imageNamed:[NSString stringWithFormat:#"%#_thumb.jpg", name]];
if (thumbImage) {
ThumbImageView *thumbView = [[ThumbImageView alloc] initWithImage:thumbImage];
[thumbView setDelegate:self];
[thumbView setImageName:name];
CGRect frame = [thumbView frame];
frame.origin.y = THUMB_V_PADDING;
frame.origin.x = xPosition;
[thumbView setFrame:frame];
[thumbView setHome:frame];
[thumbScrollView addSubview:thumbView];
[thumbView release];
xPosition += (frame.size.width + THUMB_H_PADDING);
}
}
[thumbScrollView setContentSize:CGSizeMake(xPosition, scrollViewHeight)];
}
}
#pragma mark Utility methods
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {
CGRect zoomRect;
// the zoom rect is in the content view's coordinates.
// At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
// As the zoom scale decreases, so more content is visible, the size of the rect grows.
zoomRect.size.height = [imageScrollView frame].size.height / scale;
zoomRect.size.width = [imageScrollView frame].size.width / scale;
// choose an origin so as to get the right center.
zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0);
zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
return zoomRect;
}
#pragma mark -
#pragma mark Rotation support
// Ensure that the view controller supports rotation and that the split view can therefore show in both portrait and landscape.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
#end
If you've set up your UIScrollView in a Nib file, make sure it is resizing properly when rotated (Use the Autosizing controls in the Size Inspector in Interface Builder: Both sets of arrows inside the box should be red)
Then use this to rescale when the iPad changes orientation:
- (void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation duration:(NSTimeInterval)duration{
//if your UIImageView is called zoomView use this
CGRect zoomRect=CGRectMake(0,0,zoomView.frame.size.width, zoomView.frame.size.height);
[scrollView zoomToRect:zoomRect animated:YES];}
(Sorry about the bad placement of the {} but it wasn't pasting properly as code for some reason)
Hope this helps!

Automatically Sizing UIView after Adding to Window

Note: This may be a duplicate of Subview Doesnt AutoSize When Added to Root View Controller
I have an iPad app that switches between different views in its main window. The view-switching code looks like this:
- (void)switchToViewController:(UIViewController*)viewController {
if (currentViewController != viewController) {
[currentViewController.view removeFromSuperview];
currentViewController = viewController;
[window addSubview:viewController.view];
}
}
The problem is that when the new view (a UISplitView) appears in landscape orientation, it is not sized to fill the entire window. There is a large empty black space on the right. It looks like the view is only 768 pixels wide, rather than the 1024-pixel width of the landscape window.
If I rotate the device to portrait and then back to landscape, the view sizes itself properly.
If the device is in portrait orientation, everything works fine. The UISplitView also gets sized properly if it is the first view I show. The problem only occurs if I switch to it after another view has been shown, in landscape.
So, is there some way to force iPhone OS to resize the view after it has been added to the window?
I've tried calling sizeToFit, and setNeedsLayout. I've also tried setting the view's bounds to the window's bounds, and I've tried setting the frame to match the previous view's frame.
This is absolutely possible! :-)
You can check out my repo here:
https://github.com/hfossli/AGWindowView
It will automatically deal with any rotation and framechanges so you won't have to worry about that.
If you like to worry about that then you can just cut and paste the most important parts
# 1 Add view to window
[[UIApplication sharedApplication] keyWindow] addSubview:aView];
# 2 Add listener and update view
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(statusBarFrameOrOrientationChanged:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(statusBarFrameOrOrientationChanged:) name:UIApplicationDidChangeStatusBarFrameNotification object:nil];
Remember to remove notification listening
[[NSNotificationCenter defaultCenter] removeObserver:self];
# 3 Do the math
- (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 statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation;
CGFloat angle = UIInterfaceOrientationAngleOfOrientation(statusBarOrientation);
CGFloat statusBarHeight = [[self class] getStatusBarHeight];
CGAffineTransform transform = CGAffineTransformMakeRotation(angle);
CGRect frame = [[self class] rectInWindowBounds:self.window.bounds statusBarOrientation:statusBarOrientation statusBarHeight:statusBarHeight];
[self setIfNotEqualTransform:transform frame:frame];
}
- (void)setIfNotEqualTransform:(CGAffineTransform)transform frame:(CGRect)frame
{
if(!CGAffineTransformEqualToTransform(self.transform, transform))
{
self.transform = transform;
}
if(!CGRectEqualToRect(self.frame, frame))
{
self.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;
}
}
+ (CGRect)rectInWindowBounds:(CGRect)windowBounds statusBarOrientation:(UIInterfaceOrientation)statusBarOrientation statusBarHeight:(CGFloat)statusBarHeight
{
CGRect frame = windowBounds;
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;
}
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;
}
UIInterfaceOrientationMask UIInterfaceOrientationMaskFromOrientation(UIInterfaceOrientation orientation)
{
return 1 << orientation;
}
Good luck!
This works, but it seems a little hacky:
- (void)switchToViewController:(UIViewController *)viewController {
if (viewController != currentViewController) {
UIInterfaceOrientation orientation = currentViewController.interfaceOrientation;
[currentViewController.view removeFromSuperview];
currentViewController = viewController;
UIView *view = viewController.view;
// Set appropriate view frame (it won't be autosized by addSubview:)
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
if (UIInterfaceOrientationIsLandscape(orientation)) {
// Need to flip the X-Y coordinates for landscape
view.frame = CGRectMake(appFrame.origin.y, appFrame.origin.x, appFrame.size.height, appFrame.size.width);
}
else {
view.frame = appFrame;
}
[window addSubview:view];
}
}
The window may include other UI elements besides your view. The 20 pixel difference in your example is the height of the status bar.
[[UIApplication sharedApplication] statusBarFrame].height;
Neither the window nor screen rotate. Getting their frames and using them for a rotated view will only work if you have switched the height and width.
If you are using a UIViewController, try returning YES from this method:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation; // Override to allow rotation. Default returns YES only for UIDeviceOrientationPortrait
I got the same problem, but i fixed it with this lines of code:
- (void)changeRow:(NSNotification *)notification {
[window addSubview:new.view];
[old.view removeFromSuperview];
[new.view removeFromSuperview];
[window addSubview:new.view];
}
You must add the new view, then remove the old and the new and then add the new view. I don't know why, but that works.
Fossli's answer is correct for iPad. However, I have a universal app that I needed to support. Therefore some adjustments are necessary.
Add the following to AppDelegate.h
#property (strong, nonatomic) UIImageView *imageView;
Add the following to AppDelegate.m
#synthesize imageView;
- (void)orientationChanged:(NSNotification *)notification
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (! (UIInterfaceOrientationIsLandscape(deviceOrientation) ||
UIInterfaceOrientationIsPortrait(deviceOrientation)))
{
// May be "UIInterfaceOrientationUnknown" which does not appear to be a defined value anywhere.
return;
}
[imageView setImage:[UIImage imageNamed:[Utility getBackgroundImageNameWithOrientation:deviceOrientation]]];
/*
iOS Image Sizes
iPhone/iPod Portrait 320 x 480 (640 x 960 #2x)
iPad Portrait 768 x 1004 (1536 x 2008 #2x)
Landscape 1024 x 748 (2048 x 1496 #2x)
iPad window bounds in both orientations 768 x 1024 (needs manual swap in landscape)
iPhone window bounds in both orientations 320 x 480 (needs manual swap in landscape)
Note the size variations between the required default launch image sizes and
the size of the window bounds.
iPhone/iPod only requires rotations.
iPad needs origin or size adjustments depending on orientation.
*/
CGFloat angle = 0.0;
CGRect newFrame = [[self window] bounds];
// How to get size of status bar
// Size of status bar gets all wonky on rotations so just set it manually
// CGSize statusBarSize = [[UIApplication sharedApplication] statusBarFrame].size;
CGSize statusBarSize = CGSizeMake(20.0, 20.0);
if (deviceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
angle = M_PI;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
newFrame.size.height -= statusBarSize.height;
}
}
else if (deviceOrientation == UIInterfaceOrientationLandscapeLeft)
{
angle = - M_PI / 2.0f;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
newFrame.origin.x += statusBarSize.height;
newFrame.size.width += statusBarSize.height;
}
}
else if (deviceOrientation == UIInterfaceOrientationLandscapeRight)
{
angle = M_PI / 2.0f;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
newFrame.size.width -= statusBarSize.height;
}
}
else
{
angle = 0.0;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
newFrame.origin.y += statusBarSize.height;
newFrame.size.height -= statusBarSize.height;
}
}
imageView.transform = CGAffineTransformMakeRotation(angle);
imageView.frame = newFrame;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Add background image to window with orientation changes so that it is visible in all views.
// A listener is added since subviews do not receive orientation changes.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object: nil];
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[Utility getBackgroundImageNameWithOrientation:deviceOrientation]]];
[[self window] addSubview:imageView];
return YES;
}
Add the following to Utility.h
+ (NSString *)getBackgroundImageNameWithOrientation:(UIDeviceOrientation)interfaceOrientation;
Add the following to Utility.m
+ (NSString *)getBackgroundImageNameWithOrientation:(UIDeviceOrientation)interfaceOrientation
{
NSString *imageName = nil;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
{
imageName = #"Default-Landscape~ipad.png";
}
else
{
imageName = #"Default-Portrait~ipad.png";
}
}
else
{
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
{
imageName = #"Default-Landscape~iphone.png";
}
else
{
imageName = #"Default.png";
}
}
return imageName;
}
Windows of iOS7 have different behaviors with windows of iOS8/9.
Keyboard window of iOS7 and all windows of iOS8/9 always have correct orientation & size. So you can observer the size change events and update the frame of your view.
But other windows of iOS7 always keep the portrait orientation and size. You need update transform of your view after rotation.
You need to observer UIApplicationWillChangeStatusBarOrientationNotification and update size of your UIView like this:
#interface MyView : UIView
#end
#implementation MyView
- (instancetype)init
{
if (self = [super init]) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(changeOrientationHandler:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
}
- (void)updateTransformWithOrientation:(UIInterfaceOrientation)orientation
{
CGFloat width = CGRectGetWidth(self.window.bounds);
CGFloat height = CGRectGetHeight(self.window.bounds);
if (width > height) {
CGFloat temp = width;
width = height;
height = temp;
}
CGFloat offset = (height - width) / 2;
CGAffineTransform transform;
switch (orientation) {
case UIInterfaceOrientationLandscapeLeft:
transform = CGAffineTransformMakeTranslation(-offset, offset);
transform = CGAffineTransformRotate(transform, -M_PI_2);
break;
case UIInterfaceOrientationLandscapeRight:
transform = CGAffineTransformMakeTranslation(-offset, offset);
transform = CGAffineTransformRotate(transform, M_PI_2);
break;
case UIInterfaceOrientationPortraitUpsideDown:
transform = CGAffineTransformMakeRotation(-M_PI);
break;
default:
transform = CGAffineTransformIdentity;
break;
}
self.transform = transform;
self.frame = CGRectMake(0, 0, width, height);
}
- (void)updateFrameWithOrientation:(UIInterfaceOrientation)orientation
{
CGFloat width = CGRectGetWidth(self.window.bounds);
CGFloat height = CGRectGetHeight(self.window.bounds);
if (width > height) {
CGFloat temp = width;
width = height;
height = temp;
}
switch (orientation) {
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
self.frame = CGRectMake(0, 0, height, width);
break;
default:
self.frame = CGRectMake(0, 0, width, height);
break;
}
}
- (void)updateWithOrientation:(UIInterfaceOrientation)orientation
{
BOOL isIos7 = [[UIDevice currentDevice].systemVersion floatValue] < 8.0;
BOOL isKeyboardWindow = [self.window isKindOfClass:NSClassFromString(#"UITextEffectsWindow")];
if (isIos7 == YES && isKeyboardWindow == NO) {
[self updateTransformWithOrientation:orientation];
} else {
[self updateFrameWithOrientation:orientation];
}
}
- (void)changeOrientationHandler:(NSNotification *)notification
{
[UIView animateWithDuration:0.25 animations:^{
UIInterfaceOrientation orientation = (UIInterfaceOrientation)[notification.userInfo[UIApplicationStatusBarOrientationUserInfoKey] integerValue];
[self updateWithOrientation:orientation];
}];
}
#end

How would I add a dissolve transition to my code? (comic book)

How would I add a dissolve transition to my code?
I tried looking at Apple's code but to no avail. Any ideas?
#import "ApotheosisViewController.h"
#implementation ApotheosisViewController
#synthesize scrollView1;
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
const CGFloat kScrollObjHeight = 320.0;
const CGFloat kScrollObjWidth = 480.0;
const NSUInteger kNumImages = 40;
- (void)layoutScrollImages
{
UIImageView *view = nil;
NSArray *subviews = [scrollView1 subviews];
// reposition all image subviews in a horizontal serial fashion
CGFloat curXLoc = 0;
for (view in subviews)
{
if ([view isKindOfClass:[UIImageView class]] && view.tag > 0)
{
CGRect frame = view.frame;
frame.origin = CGPointMake(curXLoc, 0);
view.frame = frame;
curXLoc += (kScrollObjWidth);
}
}
// set the content size so it can be scrollable
[scrollView1 setContentSize:CGSizeMake((kNumImages * kScrollObjWidth), [scrollView1 bounds].size.height)];
}
- (void)viewDidLoad
{
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
// 1. setup the scrollview for multiple images and add it to the view controller
//
// note: the following can be done in Interface Builder, but we show this in code for clarity
[scrollView1 setBackgroundColor:[UIColor blackColor]];
[scrollView1 setCanCancelContentTouches:NO];
scrollView1.indicatorStyle = UIScrollViewIndicatorStyleBlack;
scrollView1.clipsToBounds = NO; // default is NO, we want to restrict drawing within our scrollview
scrollView1.scrollEnabled = YES;
// pagingEnabled property default is NO, if set the scroller will stop or snap at each photo
// if you want free-flowing scroll, don't set this property.
scrollView1.pagingEnabled = YES;
// load all the images from our bundle and add them to the scroll view
NSUInteger i;
for (i = 1; i <= kNumImages; i++)
{
NSString *imageName = [NSString stringWithFormat:#"image%d.jpg", i];
UIImage *image = [UIImage imageNamed:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// setup each frame to a default height and width, it will be properly placed when we call "updateScrollList"
CGRect rect = imageView.frame;
rect.size.height = kScrollObjHeight;
rect.size.width = kScrollObjWidth;
imageView.frame = rect;
imageView.tag = i; // tag our images for later use when we place them in serial fashion
[scrollView1 addSubview:imageView];
[imageView release];
}
[self layoutScrollImages]; // now place the photos in serial layout within the scrollview
}
- (void)dealloc
{
[scrollView1 release];
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// invoke super's implementation to do the Right Thing, but also release the input controller since we can do that
// In practice this is unlikely to be used in this application, and it would be of little benefit,
// but the principle is the important thing.
//
[super didReceiveMemoryWarning];
}
#end
I can't immediately tell what the code you posted has to do with a dissolve transition.
If you are trying to go from one view to another, then you could put this in your code:
In
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
for one viewController:
self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
and when switching from one view to the other:
[self presentModalViewController:otherViewController animated:YES];