Iphone SDK - Animating Subview - iphone

I have a View that has a UIWebView, and an OptionsPane (Custom UIViewController with Custom view).
I want when the view is shown, for the options pane (located on the top of the main view) to FLIP into place. I am using the code, and I am getting a strange result.
The FIRST time the view is shown, the options pane seems to already be visible... When I hit BACK on my navController, and pull up the View again, the animation works perfectly.
Can anyone shed some light on this topic?
- (void)viewDidLoad {
[super viewDidLoad];
optionsPane=[[OptionsPaneController alloc] initWithNibName:#"OptionsPane" bundle:nil];
}
- (void)viewWillAppear:(BOOL)animated {
[optionsPane.view removeFromSuperview];
[self checkOptionsVisible];
}
-(void)checkOptionsVisible{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:[optionsPane view] cache:YES];
[[self view] addSubview:[optionsPane view]];
[theWebView setFrame:CGRectMake(0,87,320,230)];
[[optionsPane view] setFrame:CGRectMake(0,0,320,87)];
[UIView commitAnimations];
}

Hmm, I don't think the viewWillAppear message is getting sent the first time. There are two things that I read in the SDK. You should call super inside that message and there is a big warning that may apply to your first time:
Warning: If the view belonging to a view controller is added to a view hierarchy directly, the view controller will not receive this message. If you insert or add a view to the view hierarchy, and it has a view controller, you should send the associated view controller this message directly. Failing to send the view controller this message will prevent any associated animation from being displayed.
Ultimately, I would run through the debugger and make sure that viewWillAppear message is being sent when you think it is.

If I understand what your explaining, I had a very similar problem the other day.
What happening on the first load is that viewDidLoad fires first. loading the nib file takes a bit more time than it takes for the viewWillAppear to fire itself.
What we're getting is a nib loads after the viewWillApper already retired.
On any load after that, the viewDidLoad will not fire, letting the viewWillAppear to do its loyal flipping job.
What to do?
First, try to change your code to use "viewDidAppear". That should help, but you have to see if it looks good.
Another option (ugly one, I know) is to have a call to checkOptionsVisible on the viewDidLoad too.
If non of that help, I would consider a timer as a hack - if the requirements allow it.
I hope that make you closer to solve the problem.

Updated for your situation:
Instead have four views:
A backing view
The main View
The back view (options pane) 100 pixels
The front view (blank view) 100 pixels
Add the main view to the backing view as normal.
Add the front view to the backing view where you would like the options pane to appear.
make sure the front and back view have the same frame.
Use the same code as below using the methods flip the front and back views.
Original Answer
You need 3 views:
A backing view
The front View
The back view
The backing view just holds the other 2 as they flip back and forth Below are the flipping methods. I place them both in backingViewController:
- (void)displayBack{
//parent controller is an ivar so the sub-view controllers know who their daddy is
backController.parentController = self;
[UIView beginAnimations:nil context:#"flipTransitionToBack"];
[UIView setAnimationDuration:1.2];
//note self.view IS the backing view
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
//remove the front view
[[frontController view] removeFromSuperview];
//add the back view view
[self.view addSubview:[backController view]];
[UIView commitAnimations];
//giving a heads up to the view that is about to come on screen
[backController viewWillAppear:YES];
}
- (void)displayFront{
[UIView beginAnimations:nil context:#"flipTransitionToFront"];
[UIView setAnimationDuration:1.2];
[UIView setAnimationDelegate:self];
//I'm interested in knowing this has happened
[UIView setAnimationDidStopSelector:#selector(flipAnimationDidEndWithID:finished:context:)];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
//remove back view
[[backController view] removeFromSuperview];
//add the front view
[self.view addSubview:[frontController view]];
[UIView commitAnimations];
}

The view property on a UIViewController is lazily-loaded -- even when you're init-ing with a nib as you are here, the view itself doesn't actually get instantiated until the first time the property is accessed.
It's hard to know exactly what's happening without seeing more code, but you may get the results you want if you access optionsPane.view in viewDidLoad (you don't need to do anything with it, just access the property to force loading).

Related

Performing code right before dismissing a partial curl through touching on the curl itself

I'm using Storyboards for a modal segue with a partial curl effect. Input fields are on the bottom, so if the keyboard is shown, it is necessary to translate the screen with:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
self.view.superview.center = CGPointMake(self.view.center.x, [[UIScreen mainScreen] bounds].size.height/2 - 200);
[UIView commitAnimations];
After its job is done, the finishing IBAction undoes the translation before dismissing the modal view:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
self.view.superview.center = CGPointMake(self.view.center.x, [[UIScreen mainScreen] bounds].size.height/2);
[UIView commitAnimations];
...
[self dismissViewControllerAnimated:YES completion:nil];
Everything alright with this but there remains the following problem: The user can always touch the opened curl to dismiss the view. If this is done while the keyboard is shown and therewith the screen is translated, the screen flickers shortly and an abnormal program behaviour is the result. I either need to deactivate the click-on-curl-to-dismiss-the-view or I have to perform the back translation before the curl dismisses. Neither using textFieldShouldReturn to resign the first responder nor performing the back translation in viewWillDisappear/viewDidDisappear (which should in theory performed right before the dismiss?) have any effect. Does someone has any hint for me?
Create a protocol / delegate on your destination modal view then call back to your presenting viewController so your translation is handled properly once the view dismisses in the viewWillDisappear method.
Here are some examples of delegates

RootViewController causing orientation issues in IOS 6

I have an issue with changing my orientation on certain pages in my app. The shouldAutoRotatefunction does not fire on any one page. I have done some digging and hoping someone can tell me if this code is right.
I have a window, a Navigation Controller called homepageController, and a Tab Bar Controller named mainController. The app works as follows. I present the homepageController for the user to log in. Once the correct login key is entered I remove my homepageController view from the window and add the mainController view. Here is the code
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.6];
[UIView setAnimationDelegate:self];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:appDel.homePageController.view.superview cache:NO];
[appDel.homePageController.view removeFromSuperview];
[UIView commitAnimations];
[appDel.window addSubview:appDel.mainController.view];
[appDel.mainController setSelectedIndex:0];
[appDel.window bringSubviewToFront:appDel.mainController.view];
I go to my first page on the tab bar and try to rotate it, with a breakpoint on shouldAutoRotate, but it never fires.
Again I did some digging and found that my shouldAutoRotate method in my .m file for homepageController gets triggered anytime I change orientations. I looked at my xib file and this is what I have.
I saw that my homepageController is the rootViewController and when switching from tab to tab on the mainController I am using this code.
-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
UINavigationController *nav = (UINavigationController *) viewController;
[nav popToRootViewControllerAnimated:NO];
}
So seeing that my homepageController is the rootViewController that is why shouldAutoRotate always gets called there.
I am wondering if there is a better solution to this. I don't think Im doing this right at all so any guidance would be great.
Thank you
I think shouldAutoRotate is not calling because you are using addSubView: like
[appDel.window addSubView: appDel.mainController]
Set your viewcontrollers as rootviewControllers everywhere you have used as addSubview in window.
So use
appDel.window.rootViewController= appDel.mainController;
May be now shouldAutoRotate will fire event.
Hope it works for you.

iOS views animation

I am trying to create an animation for switching views on iOS devices.
I have create an application with three views and I have some navigation buttons.
The way I use to switch views is this:
-(IBAction) loadThirdView:(id)sender {
[self clearView];
self.thirdViewController.view.frame = CGRectMake(0, 208, 160, 208);
[self.view insertSubview:thirdViewController.view atIndex:0];
}
As you can see this is the action that takes place once I press the button. What I would like is the new view to appear in an animated way.
Specifically I want it to start from the left hand side of the screen and slide to the right. I do not want it just to appear.
Is this possible? how can I do it?
Oh no! Ah, no! Please do not display UIViewControllers this way.
Present your UIViewController this way:
[self presentModalViewController:self.thirdViewController animated:YES]
Before presenting it, you can change the modalTransitionStyle property of the view controller to suit your needs.
If using a UINavigationController, use instead:
[yourNavController pushModalViewController:self.thirdViewController animated:YES]
This is a nice little article (if not a little too harsh): Abusing UIViewControllers
To animate it the way you specifically would like (as the UINavigationController style is sliding in from the right), you might want to use something like what is proposed in this SO question: iPhone Pushing View Controller in a left direction
You can try
[UIView transitionFromView:currView toView:nextView duration:0.5f options:UIViewAnimationOptionTransitionFlipFromLeft completion:nil];
if you want different type of animation. There're lots AnimationsOptions you can choose, just set the options:.
Sample Code :
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.6];
yourImageVieew.alpha=0.9;//insert here what you want
[UIView commitAnimations];

UIView being pushed up (apparently)inexplicably

I have a problem with UIViews to which I really don't know how to proceed.
It will be futile to describe my problem so here are the screenshots of before and after.
Somehow the UIView gets the layout that was defined in interfacebuilder AFTER an image is chosen. Before an image is chosen it doesn't obey to its defined layout for some reason.
Before using imagePicker for picking an image:..........................After Picking image:
|
So yeah that is basically the problem. The black squares are other images and you can tell by that how it should and how it shouldn't, one of the images is being cut (normally behind the "No SIM" label.) I just put them to hide the real images on the screenshots.
So maybe is something in relation to two things I do here.
I resize the image chosen to 320-480 and put it on a smaller UIImageView before uploading it to a server.
If the user is writing on a textField the entire view is animated up, so the keyboard won't hide the textFields.
UPDATE:
I noticed this happens on a UIView that does nothing related to resizing images or textFields. This is happening too on a UIView I have where there are only 3 buttons and 2 labels. Only 5 elements. The 3 buttons are in custom mode with images. So 3 image~Buttons and 2 labels....
Thank you for your help and suggestions fellow Stackoverflowers!!! (Stackoverflowerers?)
I really have no idea on how to proceed here, though I've been playing around transforming the UIView at the viewDidLoad to no avail.
UPDATE 2:
I started to think that maybe there is something wrong with the code I use to make the transition from view to view and has nothing to do with the elements that are contained in it. Since it is happening in all my views EXCEPT the first view. So here is the code I use for the transition of views:
- (void) flipToUploadView {
UploadViewController *aUploadView = [[UploadViewController alloc] initWithNibName:#"UploadView" bundle:nil];
[self setUploadViewController:aUploadView];
[aUploadView release];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:window cache:YES];
[uploadViewController viewWillAppear:YES];
[viewController viewWillDisappear:YES];
[viewController.view removeFromSuperview];
[self.window addSubview:[uploadViewController view]];
[viewController viewDidDisappear:YES];
[uploadViewController viewDidAppear:YES];
[UIView commitAnimations];
}
Sorry don't have enough reputation to comment, but
have both views the same nib?
if not, is it possible that you just forgot to simulate the status bar in InterfaceBuilder for the few which is drawn uncorrect? and thats why the positions are different?
And i think what Tommy means is that normally you use the ModalViewcontroller to change views
[self presentModalViewController:uploadViewController animated:YES];
than all the function calls (willappear,didappear,willdissappear...) are called automatically
but i think this is not the source of the wrong displaying

How to change XIB in a tab bar application?

My iPhone app is tab bar-based, but I would like to fire an action which switches out the tab bar controller view completely and replaces everything in the window with a view from a different XIB file. I would guess this has to be done in the application delegate (since this is the "chief" class), but I don't know the right way to go from there. Does anyone know how to do what I am trying to do?
Thanks in advance!
Your tab view controller could have it's action method, such as -(IBAction)onChangeView and that method calls a method on the [[UIApplication sharedApplicaton] delegate], such as -(void)toggleScreen.
-(IBAction)onChangeView:(id)sender
{
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate toggleScreen];
}
Then in your app delegate method do something like this:
-(void)toggleScreen
{
[[[window subviews] objectAtIndex:0] removeFromSuperview];
[window addSubview:otherView];
}
It may be different if you need transitions, however.
You don't really have to go all the way to the app delegate. You can easily remove your existing views and controllers and add new views. It really does depend on what you are doing. You could, for example, temporarily put aside the existing view structure and go with something totally different, and get back to the original scheme if you want (I'm not sure of the user experience though).
In my apps, I usually have a root view controller or I use my main window to add views to and remove views from. Some views will add other views to themselves or transition another view onto the rootview or main window. Some views close themselves to reveal the view below. The options are limitless, and depend on your needs and architecture.
Thanks guys! Nick, that's just the code I needed. In case anyone finds this handy, here's the code I used to add animation to switch the view. Just put this in a method in the app delegate:
AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:#"AnotherView" bundle:nil];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.window cache:YES];
[[[window subviews] objectAtIndex:0] removeFromSuperview];
[window addSubview:[anotherViewController view]];
[UIView commitAnimations];