How to draw in UIViewController in landscape orientation on the iPhone? - iphone

there are already some questions on this topic. Unfortunately none of them helped me in anyway. So here is the thing. I am working on an app atm and it has one tabcontroller with two tabs, which contain multiple navigationcontroller on top of each other. Now in one tab at the top level navigation controller, I want to draw some graphics in landscape orientation.
Unfortunately using the shouldAutorotateToInterfaceOrientation method returning YES does not help in anyway.
Now I was wondering whether I could just hide the statusBar and the navigationBar and then draw my graphics so that it looks like it is landscape orientation. But then I also would like to add some labels. I am quite sure I also could turn those around 90 degrees. But this is probably not the right approach here. And I want to submit my app someday...
So now I was hoping someone knows whats the best approach here and how to realize it.
Thanks.

I found a solution somewhere else. The idea is to use the CGAffineTransform method. It allows you to transform the complete coordinate system of a uiview. The piece of code underneath rotatets it to landscape. Now when you draw, the drawing relates to the rotated coordinate systems and everything is drawn in landscape orientation.
CGAffineTransform transform=CGAffineTransformIdentity;
transform=CGAffineTransformRotate(transform, (90.0f*22.0f)/(180.0f*7.0f));
transform=CGAffineTransformTranslate(transform, 80, 80);
This does what I want. But anyway, if there are any other suggestions, please post them!

Related

UiViewController rotation question

I have main menu in my app supporting only landscape mode.
I implement landscape restriction by setting up UIRootViewController::shouldAutorotateToInterfaceOrientation:...
And I have another scene with portrait mode support.
So the problem appears when I pass from another scene to main menu in portrait mode: the app doesn't rotate to landscape automatically, and I can't find a code method to manually rotate it.
Is there a solution? Would be thankful.
Edit: Excuse me, I forgot to add details. RootViewController is common for menu and another scene. And what is more - these scenes are in one common view (my app uses OpenGL)
So before I enter menu from portrait scene I set UIRootViewController::shouldAutorotateToInterfaceOrientation: to return YES for landscape only.
If your other scene with portrait support is controlled by another UIViewController, then you can use that view controller's -shouldAutorotateToInterfaceOrientation: to define its behavior. In many cases, this alone should be enough. Of course, if you need to do some fancy rotations for some view controller but not for others, then things get a bit trickier.
There is no easy way to do this, except [UIDevice setOrientation:], which is not open to developers, and leads to application rejection by Apple.
You can apply a rotation to your layer which will create the exact same effect.
myview.layer.transform = CATransform3DMakeRotation(M_PI/2, 0.0f, 0.0f, 1.0f);

Views and buttons unresponsive to touches after rotation

I am coding against iOS 3.0 and I am trying to add rotation (landscape) support to my app.
Everything about the rotation was easy enough. However, after rotation to landscape mode from portrait, the right-third of the screen (480-320) is unresponsive to all events (touches, drag, etc.). I've verified that the key window is receiving the events but those events are not being passed to the buttons and UIViews on the right (in landscape) side of the screen.
I am using NSNotificationCenter to receive orientation changed events (and not using autorotate flag).
I did see: link text but that wasn't very helpful to my case.
Stuck. Need help. Thanks.
I've fixed the problem I was having .. I basically needed to do [self.navigationController.view setNeedsLayout].
The way I understand this (which maybe incorrect is that self.navigationController.view.frame was same as self.view.frame and both were equal to (x=0,y=0,width=320,height=480). I then rotated self.view by M_PI/2 and did a number of frame manipulation on select self.view.subviews to get everything to animate/position/scale correctly.
That worked out okay but the navigation controller was not willing to acknowledge touch events to parts of self.view there were to the right of 320. In essence, if this self.navigationController.view.clipsToBounds were true, it might not even have shown that part of self.view.
Anyway, setting setNeedsLayout on the navigation controller's view resolved the issue. I hope this helps someone else.

TTPhotoViewController thumbnails rotate but images don't

I have PhotoTest1Controller very similiar to the one in Three20 samples. I implemented necessary shouldRotate methods in necessary places in UITabBarController and UINavController derived classes as well as the table that contains PhotoTest1Controller.
A funny thing is happening, when in thumbnail mode, the view rotates properly, but when showing a picture it does not respond to rotation. Moreover, If I rotate in thumbnail view and then switch to single image view in that rotation, I find that the image is properly rotated in the background. It only ignores rotation when it is the topmost view!
So, my understanding is that shouldRotate events are properly propagated, but for some reason single image view does not rotate when in top view, unlike the example code which is %98 equal to my code...
I found the answer to my own problem and answered it here: TTThumbView/TTPhotoView no autorotation
Briefly: I don't know why but TTScrollView deviceOrientationDidChange method in three20 codebase is commented out! If you uncomment it, it will work.
See the code here: http://github.com/facebook/three20/blob/master/src/TTScrollView.m

Maintaining proportions when autorotating custom UIView

This is probably either real easy, real dumb, or my google fu has taken a serious turn for the worse. Anyway, I'm implementing custom view for my app, which is using pure CGContext drawing, no subviews (for now at least). The thing is, I want it to autorotate, so I have shouldAutorotateToInterfaceOrientation return YES, and voila, the view rotates. But in doing so it's not actually redrawing the content (which I assume is rendered into a texture somewhere in the framework and splashed onto a rect, but that's not really relevant here), the rect is simply stretched, squishing the content. How can I get it to simply issue a draw of a bigger area while rotating? That is, my content is bigger than the screen, and I'd simply like the viewport to change during the rotation.
I've tried setting the view's contentMode to UIViewContentModeRedraw, but that didn't do anything, I've tried playing around with the autoresizeMask stuff, but didn't seem to help either. I've also tried inserting a setNeedsDisplay in willRotateToInterfaceOrientation, however that only caused it to redraw using the new bounds (i.e. squishing it first, and then stretching it out to the right size during the rotation), which is also not what I'd like to see.
Does anyone have any idea how I might go about getting this to work?
As it turns out, it's a mix of dumb and easy. I'm posting it here if anyone should care to read it someday. They way I managed to solve it was actually sandwiching a view between window and my view (I suppose you might be able to go to work on the window directly, but it felt more intuitive this way). That is, I added my view as a child view to that view, which I'll call the frame.
The frame is a resizing as normal, however, I turn OFF resizing of child views, and make my own view LARGER than the viewing area (square actually, 480x480, so it can cover the entire screen either way). Problem solved, basically.
Now I'm playing around with animating the offset of the view in the frame during willRotateToInterfaceOrientation, to have it appear to be rotating around the center, rather than the upper left corner, but that's a different question.

What's the best way to handle landscape/portrait differences in IB?

I have a view that supports landscape and portrait viewing, with the controls all moving around when you switch from one to the other. I'm currently doing this by setting the .center of each one of my controls when the user rotates the phone. The problem is that this is tedious, and requires a lot of code, and seems to defeat the purpose of using Interface Builder in the first place.
My question is: is there a way in Interface Builder for one view to support multiple looks (one for landscape one for portrait)? If not how do other people do this with IB? Do you set up 2 views?
Edit: Just to clarify my landscape and portrait views look different, I don't want a straight transform, I actually display the data differently in landscape mode
When necessary, I add UIView objects to the view in IB which I make hidden. Give it a nice background color so you can see it, and send it all the way to the background. Then use that view's frame when you need to set the frame of an object. If you have a lot of them, you might consider using UILabel instead, so you can give it a visible name in IB.
If you're worried about memory issues, just remove all these extra UIViews in ViewDidLoad and just store their frame values in member CGRects. This only works of course if you don't have any of the views auto-resize or reposition on rotate, which you probably shouldn't anyway, in this case. I do this for resizing/repositioning for any reason, not just when the screen rotates.
I'm not 100% sure if it's possible, but have you considered using different view controllers for landscape and portrait?
The AutoSize attributes of IBOutlet objects in the Size Inspector of IB (command 3) give some pretty nice options for auto-stretching and positioning of items. You can control L/R and T/B screen positions and relative width and height. You can't get full control of the layout, but most of the basic operations are there.
The only way one view can support multiple orientations in IB is to set the autosizing mask of components to either scale and/or anchor to edges. To design a totally different layout for each orientation you need to design a portrait and landscape view separately (each in its own XIB) and switch between them programatically.