i implemented a small code to show pictures, but why is the picture on Portrait Mode optimized to the iPhone screen and NOT optimized in Landscape Mode could you please help me, here is the code:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
if(interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
imageView.frame = CGRectMake(0, 0, 320, 480);
imageView.contentMode = UIViewContentModeScaleToFill;
return YES;
} else if((interfaceOrientation == UIInterfaceOrientationLandscapeLeft ) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight)) {
imageView.contentMode = UIViewContentModeScaleToFill;
imageView.frame = CGRectMake(0, 0, 480, 320);
return YES;
}
return YES;
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[self ladeImage];
[super viewDidLoad];
}
- (void)ladeImage {
id path = #"http://172.23.1.63:8080/RestfulJava/pics";
NSURL *url = [NSURL URLWithString:path];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[UIImage alloc] initWithData:data];
imageView = [[UIImageView alloc] initWithImage:img];
imageView.frame = self.view.frame;
[self.view addSubview:imageView];
}
When the iPhone is rotated, usually the affine transformation matrix contains the transformation needed for the rotation. This means that, with your code, the transformation for the view is changed in a way that it is rotated, but since you rotate the image too, you rotate it back.
try this:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
Related
I am trying to create a custom look of my UINavigationBar. When the user puts the app in landscape, the navigationBar should be covered with an Image. When rotated back to portrait I want the View(Image) removed. Everything works fine with the code below except removing it. I can remove the View if I put the code in the same if-statement, but nothing happens if I put it in the else if-statement. Have I missed something ? / Regards
- (void) adjustViewsForOrientation:(UIInterfaceOrientation) orientation {
UIView *v = [[UIView alloc]init];
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
v.frame = CGRectMake(0,0,480,44);
v.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"navbar25g.png"]];
[self.view addSubview:v];
//[v removeFromSuperview]; <----- works if I put it here
NSLog(#"LANDSCAPE");//load the landscape view
}
else if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
[v removeFromSuperview]; <----- Not working
NSLog(#"PORTRAIT"); //load the portrait view
}
}
the reason that you cannot remove it is every time you go into the method you create a new instance of the UIView *v.
Create an instance variable then assign the view to that. Once it is assigned you can then remove or add as needed.
If you do not want to use an instance variable then you can give the view a tag i.e.
UIView *v = nil;
v = [self.view viewForTag:1000];
if (!v) {
v = [[UIView alloc] init];
v.tag = 1000;
v.frame = CGRectMake(0, 0, 480, 44);
v.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"navbar25g.png"]];
}
Now you can do your adding and removing for it.
Have you tried UIAppearance?
[[UINavigationBar appearance] setBackgroundImage:nil barMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundImage:image barMetrics:UIBarMetricsLandscapePhone];
I have a imageView embedded in a scrollView. The imageView needs to be downloaded from the Internet (through flickr api), so I add a thread to handle this. But what am I supposed to do after I finished downloading the image? How can I reload my imageView?Here's my code.
In fact, it is working fine. but the imageView's size is (0, 0). How can I fix that?
- (void)viewDidLoad
{
[super viewDidLoad];
if (!self.myImage)
{
UIActivityIndicatorView* spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[spinner startAnimating];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinner];
dispatch_queue_t downloadQueue = dispatch_queue_create("flickr downloader (photo)", NULL);
dispatch_async(downloadQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:[FlickrFetcher urlForPhoto:self.photo format:FlickrPhotoFormatLarge]];
dispatch_async(dispatch_get_main_queue(), ^{
self.myImage = [UIImage imageWithData:data];
[self.imageView setImage:self.myImage];
[self viewDidLoad];
[self viewWillAppear:NO];
NSLog(#"imageViewSet!");
self.navigationItem.rightBarButtonItem = nil;
});
});
dispatch_release(downloadQueue);
}
else
{
NSString* imageTitle;
if ([[self.photo objectForKey:#"title"] length] > 0)
imageTitle = [self.photo objectForKey:#"title"];
else if ([[self.photo valueForKeyPath:#"description._content"] length] > 0)
imageTitle = [self.photo valueForKeyPath:#"description._content"];
else imageTitle = #"Unknown";
[[self navigationItem] setTitle:imageTitle];
self.scrollView.delegate = self;
self.scrollView.contentSize = self.imageView.image.size;
}
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
double scale = self.imageView.bounds.size.width * 1.0 / self.myImage.size.width;
if (scale > self.imageView.bounds.size.height * 1.0 / self.myImage.size.height)
scale = self.imageView.bounds.size.height * 1.0 / self.myImage.size.height;
NSLog(#"imgview%g, %g",self.imageView.bounds.size.width, self.imageView.bounds.size.height);
NSLog(#"img%g, %g",self.myImage.size.width, self.myImage.size.height);
self.imageView.frame = CGRectMake(0, 0, self.imageView.image.size.width, self.imageView.image.size.height);
[self.scrollView setZoomScale:scale];
}
The usual way is to call:
[self.imageView setNeedsDisplay];
Edited to Add:
I just realized you said the image view is still (0,0). From the docs :
Setting the image property does not change the size of a UIImageView.
Call sizeToFit to adjust the size of the view to match the image.
I am loading a view as soon as the user rotates to landscape but when I use view.bounds in viewDidLoad it is still in portrait.
Here the code where I load the view which is triggered from a notification
- (void)orientationChanged:(NSNotification *)notification
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)
{
[self presentModalViewController:self.graphViewController animated:YES];
isShowingLandscapeView = YES;
} else if (deviceOrientation == UIDeviceOrientationPortrait && isShowingLandscapeView)
{
[self dismissModalViewControllerAnimated:YES];
isShowingLandscapeView = NO;
}
}
And in the graphViewController in viewDidLoad I use self.view.bounds to initialise a core-plot.
This is how it looks like
Any hint on how to fix that?
Thanks a lot
EDIT
in viewDidLoad
// Create graph from theme
graph = [[CPTXYGraph alloc] initWithFrame:self.view.bounds];
CPTTheme *theme = [CPTTheme themeNamed:kCPTDarkGradientTheme];
[graph applyTheme:theme];
CPTGraphHostingView *hostingView = [[CPTGraphHostingView alloc] initWithFrame:self.view.bounds];
hostingView.collapsesLayers = NO; // Setting to YES reduces GPU memory usage, but can slow drawing/scrolling
hostingView.hostedGraph = graph;
[self.view addSubview:hostingView];
Assuming CPTGraphHostingView will adjust the orientation of how it renders, you need to set the autoresizingMask on it. This determines how views resize when their superviews resize, which is happening in this case.
hostingView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
It's not the correct approach. You should be doing this stuff in layoutSubviews. It will be called first time in, and subsequently each time orientation changes. Do something like this:
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect frame = self.bounds;
// Do your subviews layout here based upon frame
}
I am creating a application in which I can need to play a video which I do by mpmovieplayer controller .Now i nee to do this for both orientation .But the frame doesnt get set properly .
The code is as follws
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
[self shouldAutorotateToInterfaceOrientation:[UIDevice currentDevice].orientation];
NSURL *temp = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"Floating" ofType:#"mp4"]];
mpviewController = [[MPMoviePlayerViewController alloc] initWithContentURL:temp];
mpviewController.view.frame = CGRectMake(0, 0, 768, 1024);
mpviewController.view.backgroundColor = [UIColor clearColor];
mpviewController.moviePlayer.movieSourceType = MPMovieSourceTypeFile;
mpviewController.view.userInteractionEnabled= NO;
mpviewController.moviePlayer.fullscreen= YES;
mpviewController.moviePlayer.controlStyle = MPMovieControlStyleNone;
[[mpviewController moviePlayer] play];
[self.view addSubview:mpviewController.view];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
currentOrientation = interfaceOrientation;
//[self SetInterface];
if(interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
mpviewController.view.frame = CGRectMake(0, 0, 768, 1024);
else if(interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight)
mpviewController.view.frame = CGRectMake(0, 0, 1024, 768);
return YES;
}
I dont know where I am wrong.Please let me know for any chages to make in code. So as to get proper orientation.
Ragards Abhi
First
I believe you don't need to resize the mpviewController as it will resize it self alone.
you should only set the -
Second
In the shouldAutorotateToInterfaceOrientation you only set the supported directions in shouldAutorotateToInterfaceOrientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
If it dose not do it you change the view properties in -
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
if (UIInterfaceOrientationIsPortrait(interfaceOrientation)){
//do what you want for portrait
}else{
//do what you want for landscape
}
}
you should only return either YES or NO in shouldAutorotateToInterfaceOrientation: method, it's called by framework only to get the information about the supported orientation in your controller, Read the apple documentation for the same.
you need to register for the orientation change notifictaion
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
Implement your orientationChanged: method.
//********** ORIENTATION CHANGED **********
- (void) orientationChanged:(NSNotification *)note
{
NSLog(#"Orientation has changed: %d", [[note object] orientation]);
//Put your code here from shouldAutorotateToInterfaceOrientation:
}
Not forget it to remove .
[[NSNotificationCenter defaultCenter] removeObserver:self];
Here are some link
Device orientation - autorotate?
Orientation Changed Notification
No need to change any codings .. simple insert the following codings to the application , it will automatically detect the orientation...
UINavigationBar *bar = [self.navigationController navigationBar];
[bar setTintColor:[UIColor blackColor]];
NSBundle *bundle = [NSBundle mainBundle];
NSString *moviePath = [bundle pathForResource:#"sharkdivertrailer" ofType:#"mp4"];
NSURL *movieURL = [[NSURL fileURLWithPath:moviePath] retain];
MPMoviePlayerController *theMovie = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
theMovie.view.frame = CGRectMake(184, 200, 400, 300);
[theMovie play];
MPMoviePlayerViewController *moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:movieURL];
[self presentMoviePlayerViewControllerAnimated:moviePlayer];
My splash screen is working, but my app works on landscape mode, and the splash screen shows in the default portrait mode.
How can I start the app so that the splash screen rotates between landscape modes like my app?
I'm using the following code:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight)
return YES;
else {
return NO; }
}
and for the splash screen
-(void)displayScreen {
UIViewController *displayViewController=[[UIViewController alloc] init];
displayViewController.view = displaySplashScreen;
[self presentModalViewController:displayViewController animated:NO];
[self performSelector:#selector(removeScreen) withObject:nil afterDelay:3.0];
}
-(void)removeScreen
{ [[self modalViewController] dismissModalViewControllerAnimated:YES];
}
But how can I put the rotate inside the display screen?
Aha. If you want to display your own splash screen, you should create a special view controller for that, which you already did. I think you can simplify the autorotation query code:
- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) foo
{
return YES; // all interface orientations supported
}
Now you have to think about the splash screens for different orientations. Do you have a separate splash image for landscape and portrait? If yes, you can do something like this:
- (UIView*) startupImageWithOrientation: (UIInterfaceOrientation) io
{
UIImage *img = [UIImage imageNamed:[NSString
stringWithFormat:#"Default-%#.png", UIInterfaceOrientationName(io)]];
UIView *view = [[UIImageView alloc] initWithImage:img];
[view setFrame:[[UIScreen mainScreen] applicationFrame]];
return [view autorelease];
}
- (void) loadView
{
self.view = [self startupImageWithOrientation:self.interfaceOrientation];
}
- (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) io
duration: (NSTimeInterval) duration
{
self.view = [self startupImageWithOrientation:io];
self.view.transform = CGAffineTransformFromUIOrientation(io);
}
There are two utility functions called, you can stuff these into a separate file:
NSString *UIInterfaceOrientationName(UIInterfaceOrientation io)
{
return UIInterfaceOrientationIsPortrait(io) ? #"Portrait" : #"Landscape";
}
CGAffineTransform CGAffineTransformFromUIOrientation(UIInterfaceOrientation io)
{
assert(io <= 4);
// unknown, portrait, portrait u/d, landscape L, landscape R
static float angles[] = {0, 0, M_PI, M_PI/2, -M_PI/2};
return CGAffineTransformMakeRotation(angles[io]);
}
It’s a bit messy, I’d be interested in simpler solution myself.
#zoul - loving this solution so far. however, if/when that view has any subviews - they don't show up. any ideas?
update:
fixed this issue by adding a subview to the UIView created in -startupImageWithOrientation: not self.view.
- (UIView *)startupImageWithOrientation:(UIInterfaceOrientation)io{
UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:#"Default-%#.png", UIInterfaceOrientationName(io)]];
UIView *aView = [[UIImageView alloc] initWithImage:img];
[aView setFrame:[[UIScreen mainScreen] applicationFrame]];
// define the version number label
self.versionNumberLabel_iPadSplashScreen.text = [NSString stringWithFormat:#"Version %#",
[[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"]];
[aView addSubview:self.versionNumberLabel_iPadSplashScreen];
return [aView autorelease];
}
The resolution of your defult.png can effect your apps orientation if you have locked orientations.
For example if a 1024x768 splash image is used and the initial view doesn’t support portrait viewing through orientation locks this can cause visual UI objects to appear off screen (especially when animation is involved) as the view will try and present itself in a portrait configuration even though the device may be in landscape.
Generally, 1024x768 images imply portrait while 768x1024 images imply landscape.
If this isn't enough, or your wanting to seamlessly go from the initial default image into e.g a login screen, then you can use a viewcontroller to 'continue' the splash .
Load all the normal viewControllers into the window, then put your 'splash' viewController in then in your splashController use shouldAutorotateToInterfaceOrientation method to set the right image (on an ImageViewController):
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
switch ([[UIDevice currentDevice] orientation])
{
case UIInterfaceOrientationLandscapeRight:
splashImage.image = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"Default"] ofType:#"png"]];
break;
case UIInterfaceOrientationPortrait:
splashImage.image = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"Default"] ofType:#"png"]];
break;
default:
splashImage.image = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"Default2"] ofType:#"png"]];
break;
}
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
The configuration of the images i have used may not suit you, so some experimentation might be needed.
- (void)willAnimateFirstHalfOfRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (toInterfaceOrientation == UIInterfaceOrientationPortrait)
{
// take action here , when phone is "Portrait"
}
else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft)
{
action 4 LandscapeLeft
}
else if (toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
//PortraitUpsideDown
}
else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
//LandscapeRight
}
note that you should return YES the method shouldAutorotateToInterfaceOrientation: