I have ViewControllers A and B on the navigation stack. A does not support landscape orientation, B does. If the user rotates to landscape while viewing B and then taps the Back button, A is now in landscape. How do I prevent this? Is there a good reason the shouldAutorotateToInterfaceOrientation method of A is not respected?
This is really very annoying thing about view controllers. And It seems to be no fix for autorotation. Maybe, the best would be return NO from B's shouldAutorotateToInterfaceOrientation and then perform view rotation manually. Then it won't affect A.
yes, i hate that too...
all i found to solve it was to do it by myself:
- (void)myAutomaticRotation{
if (A.view.frame.size.width > A.view.frame.size.height) {
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration: 0.5f];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(M_PI/2);
self.view.bounds = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f);
A.view.frame = CGRectMake(0,0,320, 480);
[UIView commitAnimations];
}
}
you can call myAutomaticRotation in a main/super UIViewController when you navigate to A.view,
and in that same place you should use:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
}
where you can check the view used (A,B) and allowing landscape mode just for B...
luca
Related
I want to add a view under my tab bar analog in iOS and then show it with animation coming from behind it. But when I use my code, the view that must come from behind my tab bar overlaps my tab bar for a while.
This is my code:
- (void)handlePressedButton {
if (pressedButton.selected) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
CGAffineTransform transform1 = CGAffineTransformMakeTranslation(-196.0, 0.0);
CGAffineTransform transform2 = CGAffineTransformMakeTranslation(0.0, 0.0);
[leftPanelView setTransform:transform1];
[movedView setTransform:transform2];
[UIView commitAnimations];
pressedButton.selected = NO;
}
else {
pressedButton.selected = YES;
if (leftPanelView) {
[leftPanelView removeFromSuperview];
leftPanelView = nil;
}
CGRect viewFrame = CGRectMake(-196, 0, 236, 748);
leftPanelView = [[UIView alloc] initWithFrame:viewFrame];
leftPanelView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"left-nav-content.png"]];
// Code to populate leftPanelView according to what button is pressed.
[self populateLeftPanelView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[self.view addSubview:leftPanelView];
CGAffineTransform transform1 = CGAffineTransformMakeTranslation(236.0, 0.0);
CGAffineTransform transform2 = CGAffineTransformMakeTranslation(112.0, 0.0);
[leftPanelView setTransform:transform1];
[movedView setTransform:transform2];
[UIView commitAnimations];
}
}
Here the leftPanelView is the view that must come under a tab bar. Moved view is another view, that is at the right of left panel (don't mind it)
Besides addSubview, there are other methods you can rely on to add your view:
– insertSubview:aboveSubview:
– insertSubview:belowSubview:
– insertSubview:atIndex:
You can control the index (actually z-index, or layer order) of the view using these methods.
try sendSubviewToBack
[self.view sendSubviewToBack:leftPanelView];
Swift 5
Insert a view below another view in the view hierarchy:
view.insertSubview(subview1, belowSubview: subview2)
Insert a view above another view in the view hierarchy:
view.insertSubview(subview1, aboveSubview: subview2)
Insert a subview at the specified index:
view.insertSubview(subview, at: index)
Move the specified subview so that it appears behind its siblings:
subview1.sendSubviewToBack(subview2)
Move the specified subview so that it appears on top of its siblings:
subview1.bringSubviewToFront(subview2)
Exchange the subviews at the specified indices:
view.exchangeSubview(at: index1, withSubviewAt: index2)
Oh, I found a solution myself. I added after this:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[self.view addSubview:leftPanelView];
this line:
[self.view sendSubviewToBack:leftPanelView];
In Swift 5
self.view.sendSubviewToBack(leftPanelView)
Another nice idea is to give the Subviews a tag.
Swift
mainView.addSubView(topView)
mainView.addSubView(bottomView)
topView.tag = 2
mainView.insertSubview(bottomView, belowSubview: mainView.viewWithTag(2))
Objective-C
Insert a view below another view in the view hierarchy:
- (void)insertSubview:(UIView *)subview1
belowSubview:(UIView *)subview2;
Insert a view above another view in the view hierarchy:
- (void)insertSubview:(UIView *)subview1
aboveSubview:(UIView *)subview2;
Insert a subview at the specified index:
- (void)insertSubview:(UIView *)view
atIndex:(NSInteger)index;
Move the specified subview so that it appears behind its siblings:
- (void)sendSubviewToBack:(UIView *)view;
Move the specified subview so that it appears on top of its siblings:
- (void)bringSubviewToFront:(UIView *)view;
Exchange the subviews at the specified indices:
- (void)exchangeSubviewAtIndex:(NSInteger)index1
withSubviewAtIndex:(NSInteger)index2;
I guess this is quite basic, but I was wondering if there is an easy way to animate an entire NIB onto the screen... coming from the right. Ideally, I'd like it to bounce a bit once it stops (i.e. if the NIB is supposed to scroll to position X = 0, I'd like to go it slightly negative before coming back to 0).
This is what I have so far:
[UIView animateWithDuration:0.5
delay:0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
TabsEdit *tEdit = [[TabsEdit alloc] initWithNibName:#"TabsEdit" bundle:nil];
self.tabsEdit = tEdit;
[self.view addSubview:tEdit.view];
[tEdit release];
}
completion:^(BOOL finished){
}
Is there any easy solution or will I need to animate every single element in the NIB into view and then add my little bounce effect to it?
I'd be grateful for any suggestions of how to achieve this efficiently.
To get more complicated animations (if you want to have more segments to the bouce), you should go down to the CoreAnimation layer and define keyframes. Else have a series of embedded animateWithDuration/Completions, with each one doing a different part of the bounce). If all elements of a view are subviews, then when the view is animated, its subviews will follow.
one move repeat to bounce.
[UIView beginAnimations:#"move" context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.25];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
if(movingIn){
view.frame = CGRectMake(0.0f, view.frame.origin.x, .view.frame.size.width, view.frame.size.height);
}else{
view.frame = CGRectMake(320.0f, view.frame.origin.x, .view.frame.size.width, view.frame.size.height);
}
[UIView commitAnimations];
I am using this code to for flip transition.
MyViewController *viewController = [[MyViewController alloc] init];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:YES];
[self.navigationController pushViewController:viewController animated:NO];
[UIView commitAnimations];
[viewController release];
But instead of fliping from right, its flipping from top. My application works only in landscape mode.
Please help.
I don't know what Apple was thinking when they developed this API. Here's the workaround I used:
// Assume this code is in a view controller subclass
- (UIViewAnimationOptions)viewAnimationOptionTransitionFlipFromRight
{
switch (self.interfaceOrientation) {
case UIInterfaceOrientationPortrait:
return UIViewAnimationOptionTransitionFlipFromRight;
case UIInterfaceOrientationLandscapeLeft:
return UIViewAnimationOptionTransitionFlipFromBottom;
case UIInterfaceOrientationLandscapeRight:
return UIViewAnimationOptionTransitionFlipFromTop;
case UIInterfaceOrientationPortraitUpsideDown:
return UIViewAnimationOptionTransitionFlipFromLeft;
}
}
You can adjust the code accordingly if you want to flip in a different direction. If you want to use the page curl transitions, however, I'm afraid you may be completely out of luck.
The animation constants have been defined with portrait mode in mind. If you define your application to be landscape mode only, you have to think about these animation constants with your head tilted 90 degrees.
Let's say your device's top is titled to the left, than you would set the animation with
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.navigationController.view cache:YES];
and it would curl from the right. That's because the bottom of the device faces to the right in this case.
The bad thing is that UIViewAnimationTransitionFlipFromBottom is not defined. I guess you could rotate the coordinate system of the animation with 90 degrees, but I can't help you with that.
Hi I have a problem when adding a subview when my app is in landscape. When the view gets loaded it is in portrait mode so part of the view is missing and I can see the main view on the right hand side. If I load the subview in portrait mode then rotate the iPhone it rotates to landscape no problem. I have googled this lots and it seems to be a common problem yet I am unable to find a solution. Please can someone help?
This is my code to add the view...
PreferencesViewController *screen = [[PreferencesViewController alloc]initWithNibName:nil bundle:nil];
[self.view addSubview:screen.view];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
[UIView commitAnimations];
Thanks :-)
[self.view addSubview:viewSpinner];
viewSpinner.frame = self.view.frame;
[viewSpinner setNeedsLayout];
This works for me (Y)
try to set the frame of the subview
[screen.view setFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
Are you creating the preference views controller using a xib? Dont forget to set the parent view to auto resize its subviews, and set the child view's autoresizingmasks so its parent view can auto adjust its height and width appropriately.
How can I autorotate an image from portrait to landscape mode on the IPhone?
You have to implement shouldAutorotateToInterfaceOrientation method in your controller, like this
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
Apply proper transformation to the view and adjust its frame bounds
In my app I've done it this way (very likely not the best one):
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration: 0.5f];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(-M_PI/2);
self.view.bounds = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f);
self.view.center = CGPointMake(160.0f, 240.0f);
[UIView commitAnimations];
If you want to display a new and different view, the simplest and cleanest solution is to push a new view controller (presentModalViewController) that only supports landscape mode (in shouldAutorotateToInterfaceOrientation:).