changing UIWebView frame on device rotation - ios

I'm developing an app that is locked to portrait mode. However one view is acting as a full screen 'player' for various media types.
I'm using a UIView subclass that has a UIWebview subview to play the media.
This is presented full screen on top of the viewing stack. My problem arises in making only this view rotate for landscape content - e.g. videos & pdfs.
To do the rotation I'm setting an observer in the init method:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(deviceRotated:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
and rotating as so:
- (void)deviceRotated:(NSNotification *)notification {
UIDeviceOrientation orientation = [[notification object] orientation];
if (orientation == UIDeviceOrientationLandscapeLeft) {
[UIView animateWithDuration:0.6f delay:0.0 options:UIViewAnimationCurveEaseInOut
animations:^{ [self.webView setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)]; }
completion:nil];
}
else if (orientation == UIDeviceOrientationLandscapeRight) {
[UIView animateWithDuration:0.6f delay:0.0 options:UIViewAnimationCurveEaseInOut
animations:^{ [self.webView setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)]; }
completion:nil];
}
else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
[UIView animateWithDuration:0.6f delay:0.0 options:UIViewAnimationCurveEaseInOut
animations:^{ [self.webView setTransform:CGAffineTransformMakeRotation(M_PI)]; }
completion:nil];
}
else if (orientation == UIDeviceOrientationPortrait) {
[UIView animateWithDuration:0.6f delay:0.0 options:UIViewAnimationCurveEaseInOut
animations:^{ [self.webView setTransform:CGAffineTransformMakeRotation(0.0)]; }
completion:nil];
}
}
I know I need to alter the frame size for self.webView when rotating, but I am getting strange results.
I've tried setting to container view as a large 'square' with length [[UIScreen mainscreen] bounds].size.height and placing the web view in the middle, but it moves about inconsistantly - it seems as if the width & height values are getting set from the dimensons before the rotation.
I've also tried setting autoResizingMask flexible height & width, but as the container view is off the screen this stretches the web view offscreen also.

Related

scrollView.setContentOffset does not scroll the view, at all

I've been following this and a bunch of other tutorials/blogs,etc trying to get my view to scroll when the user hits "return" and ends on a UITextField that is being covered by the keyboard but nothing is actually working.
I'm wondering what must I be doing or missing that is causing this?
Basically:
the user wants to do something in the app: add a credit card
show a UIView that contains all the CC fields
1/2 of the UITextFields are covered by the keyboard
scroll the view when the user gets there.
Nothing is happening. The code for detecting the 'covered by keyboard' case is being hit and executed but: [self.scrollView setContentOffset:scrollPoint animated:YES] has no effect at all.
Thoughts?
Reveal screenshot:
code: same as the tutorial in the link. Nothing new there.
Did you check the contentSize property?
To make a scroll view scrollable, the content must be larger than the display area(usually the bounds of the scrollview).
You can achieve this by explicitly setting the contentSize property which is CGSizeZero by default
In addition, setting the contentInset property to adjust the size of display area(in this case you can set bottom value equals keyboard height) when the keyboard is popped up
Try this,
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[UIView animateWithDuration:0.25 animations:^{
[yourTextField setFrame:CGRectMake(yourTextField.frame.origin.x, yourTextField.frame.origin.y-keyboardHeight, yourTextField.frame.size.width, yourTextField.frame.size.height)];
}];
}
and
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[UIView animateWithDuration:0.25 animations:^{
[yourTextField setFrame:CGRectMake(yourTextField.frame.origin.x, yourTextField.frame.origin.y+keyboardHeight, yourTextField.frame.size.width, yourTextField.frame.size.height)];
}];
}
What I do to avoid the textField being covered by the keyboard is to animate the textfield to the top of the screen when the user touches it to start entering something with the keyboard and animate it back when done. It is much more elegant in my opinion. Maybe that could be an alternative solution for you... I do it for the different screensizes with different numbers... you might need to adjust it of course...
So listen to the textField delegate and in
- (void)textFieldDidBeginEditing:(UITextField *)textField {
you do
CGSize result = [[UIScreen mainScreen] bounds].size;
if(result.height == 480){
({[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.35f]; CGRect frame = self.view.frame; frame.origin.y = -196; [self.view setFrame:frame]; [UIView commitAnimations];});
}
if(result.height == 568){
({[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.35f]; CGRect frame = self.view.frame; frame.origin.y = -196; [self.view setFrame:frame]; [UIView commitAnimations];});
}
if(result.height == 667){
({[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.35f]; CGRect frame = self.view.frame; frame.origin.y = -238; [self.view setFrame:frame]; [UIView commitAnimations];});
}
if(result.height == 736){
({[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.35f]; CGRect frame = self.view.frame; frame.origin.y = -251; [self.view setFrame:frame]; [UIView commitAnimations];});
}
and in
- (void)textFieldDidEndEditing:(UITextField *)textField {
you just animate back
({[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.35f]; CGRect frame = self.view.frame; frame.origin.y = 0; [self.view setFrame:frame]; [UIView commitAnimations];});

How to stop reloadData from moving a table view

I have a table view that I animate to a new position when pressing a button. It covers a small portion of the screen at the bottom and then pressing the button calls a method that makes it cover about half the screen. This way the user can choose a file from the table view.
However, it seems that when I call reloadData, the table view moves back to its original position, and I would like to stop that from happening so that the user doesn't need to press the button every time (such as with deleting a file, renaming a file, or adding a new file to the table view).
Any ideas how I could accomplish this?
I've included code. The file IBAction is what happens when the button is pressed.
-(IBAction)file:(id)sender {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.2];
if (self.tableView.frame.origin.y == 457) {
[self tableAppear];
}
else {
[self tableDisappear];
}
}
-(void)tableDisappear {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.2];
if ([[UIScreen mainScreen] bounds].size.height == 568) { [self.tableView setCenter:CGPointMake(160, 545)];
}
else { [self.tableView setCenter:CGPointMake(160, 545)];
}
[UIView commitAnimations];
}
-(void)tableAppear {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.2];
if ([[UIScreen mainScreen] bounds].size.height == 568) { [self.tableView setCenter:CGPointMake(160, 390)];
}
else { [self.tableView setCenter:CGPointMake(160, 390)];
}
[UIView commitAnimations];
}
This is most likely a consequence of auto layout (when the screen needs to be redrawn, all views will revert to the positions determined by their constraints rather then any frames that you set). You can turn off auto layout to see if this is the problem. If you want to use auto layout, then you need to do any moving or resizing of view using constraints rather than setting views.

Transitioning UIViews

I am using Facebook SDK in my game in order to post some scores on Facebook.
My code is using the Cocos2D framework so I had to add some code to enable the use of UIView.
Everything works fine except that the view appears in portrait orientation despite the fact that my nibs attributes indicate landscape, the ShouldautoRotate method returns landscape, and the app orientation is also the to landscape.
here is the code that set up the view:
// share to facebook methods
-(void)shareFacebookSelected
{
[[SimpleAudioEngine sharedEngine]stopBackgroundMusic];
[[CCDirector sharedDirector] pause];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
myViewController1 = [[HFViewController alloc] initWithNibName:#"HFViewController_iPhone" bundle:nil];
} else {
myViewController1 = [[HFViewController alloc] initWithNibName:#"HFViewController_iPad" bundle:nil];
}
UIWindow* window = [[[UIApplication sharedApplication] windows] objectAtIndex:0];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.75];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:window cache:YES];
[[[CCDirector sharedDirector]view] removeFromSuperview];
myViewController1.view.hidden = false;
[window addSubview:myViewController1.view];
[UIView commitAnimations];
}
I also enabled a button to return to the normal cocos game and remove the UIView but upon return even my main game orientation has changed to portrait.
any ideas???
The following lines solved my problem:
#define DegreesToRadians(x) ((x) * M_PI / 180.0)
CGRect screenRect = [[UIScreen mainScreen]bounds];
myViewController1.view.transform = CGAffineTransformMakeRotation(DegreesToRadians(90));
myViewController1.view.hidden = false;
myViewController1.view.frame = screenRect;
I basically rotated the view 90 degrees, not the most elegant solution, just brute force but it works. I would still like to understand why it renders the way it does, oh well

Widgets and Screen Rotation in IOS

I have an ipad app using storyboards which is laid out in landscape mode. All the labels and and imageviews are centered in the storyboard. It looks great in landscape mode, but as soon as the tablet is rotated, the ipad redraws the widgets using the landscape screen parameters, rather than the portrait mode ones. How do I get the widgets to redraw when in the correct mode?
You can use auto resizing to redraw your view to Portait mode.
Or
You can use interfaceOrientation to set a exact position for the views which is not aligned in Portait mode something like the code below
Note: Change Widgets frame only if it is improper.
Learn to position your views using auto resizing... which is more appreciated.
Animate it to have good orientation feel.
For ios 6 use- (BOOL) shouldAutorotate
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait||
interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
//Code
dispatch_async(dispatch_get_main_queue(), ^{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
_btn1.frame = CGRectMake(190, 270, 137, 240);
_btn2.frame = CGRectMake(440, 270, 137, 240);
_btn3.frame = CGRectMake(300, 40, 137, 240);
[UIView commitAnimations];
});
}
else if (interfaceOrientation == UIInterfaceOrientationLandscapeRight||
interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
{
dispatch_async(dispatch_get_main_queue(), ^{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
_btn1.frame = CGRectMake(250, 180, 137, 240);
_btn2.frame = CGRectMake(640, 180, 137, 240);
_btn3.frame = CGRectMake(440, 40, 137, 240);
[UIView commitAnimations];
});
//Code
}
return YES;
}

Providing autorotation support to a subview loaded programmatically - iPad

I have an iPad project structured as:
- AppDelegate
- MainWindow
- View Controller
-- View
The View Controllers .m file loads another view programmatically and positions it on the screen. This view is going to be slid in and out.
I do this:
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect viewRect = CGRectMake(0, 0, 0, 0);
CalculatorView *v = [[[CalculatorView alloc]
initWithFrame:viewRect] autorelease];
[self.view.window addSubview:v];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
v.view.frame = CGRectMake(0, 0, 460, 320);
[UIView commitAnimations];
}
The issue that I am having is that the subview I'm adding here doesnt' seem to have the correct orientation. The project supports ONLY landscape, and launches to landscape. The container view is fine, and it contains some buttons which are fine as well. However this programmatically loaded view is stuck in Portrait mode. I have provided the following auto-rotation code (In the loaded view's .m):
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
But it never gets called.
So, how can I get the programmatically added subview to load in landscape and NOT portrait mode?
TIA!
The UIView class does not receive orientation change messages.
(specially the shouldAutorotateToInterfaceOrientation method, which is a UIViewController Method)
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006926-CH3-SW23
You will have to manually add a method in your view to inform it that the orientation has changed and you should call this method in your controller shouldAutorotateToInterfaceOrientation method.
To do that you will have to create a reference to you view in your controller and take care of the memory yourself.
#interface MyController : UIViewController {
CalculatorView *_calculatorView;
}
#end
#implementation MyController
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect viewRect = CGRectMake(0, 0, 0, 0);
//inits _calculatorView without the autorelease. Will be released in the dealloc method
_calculatorView = [[CalculatorView alloc]
initWithFrame:viewRect];
[self.view.window addSubview:v];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
_calculatorView.view.frame = CGRectMake(0, 0, 460, 320);
[UIView commitAnimations];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
//calls custom interface orientation method
[_calculatorView MyInterfaceChangedCustomMethod:interfaceOrientation];
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
-(void) dealloc {
[_calculatorView release];
[super dealloc];
}
#end
EDIT: If you CalculatorView is simple and all you need is to change its frame properly after the device rotation, I think the best approach would be using you view's autoresizingMask similar to the following
_calculatorView = [[CalculatorView alloc]
initWithFrame:viewRect];
_calculatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

Resources