How to animate View swap on simple View iPhone App? - iphone

Have a simple iPhone app with a single UIViewController and two Views in one xib.
the first view is very simple with a button and upon button press the second more complex view is loaded via setting the view property on the controller.
what I would like is to animate the view swap (flip the views).
The samples I have seen all require having multiple view controllers and building a hierachy, but that would be overkill in this case, any suggestions?

Make sure you declare IBOutlets for the two views in your view controller I am assuming that in your xib you have a 'container view' that occupies the whole screen, and two views of the same size that you add to this contatiner (one for each side of your 'flip'):
//Inside your .h:
IBOutlet UIView *firstView;
IBOutlet UIView *secondView;
Make sure on initial load you have the firstView show up:
-(void) viewDidLoad {
NSAssert(firstView && seconView, #"Whoops: Are first View and Second View Wired in IB?");
[self.view addSubview: firstView]; //Lets make sure that the first view is shown
[secondView removeFromSuperview]; //Lets make sure that the second View is not shown at first
}
Then you can wire up a button like this, make sure the button is wired to this metod in IB:
-(IBAction) flipButtonPressed:(id) sender {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
if ([firstView superview]) {
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
[firstView removeFromSuperview];
[self.view addSubview:secondView];
}
else if ([secondView superview]) {
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
[secondView removeFromSuperview];
[self.view addSubview:firstView];
}
[UIView commitAnimations];
}

Related

How to check if a view controller's view is getting flipped/toggled

I need to somehow check in the code if by clicking a button (doing an action), it is getting the view controller's view toggled
I am using
if ([currentViewController.view respondsToSelector:#selector(setAnimationTransition:forView:cache:)])
but this one doesn't look like working
Usually this code used to get the view toggled
[UIView beginAnimations:Nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self cache:YES];
[mainView removeFromSuperview];
[self addSubview:infoView];
[UIView commitAnimations];
It looks like you're having the view controller's view manage the flipping. I'm sure that can work, but it's more common to let the view controller manage that sort of thing. If you do that, then the view controller will know when the view has been flipped, because it did the flipping.
If you're going to stick with having the view controller's view manage the transition, then you'll have to have the view controller ask its view about the state of the interface. From your view controller, you'd do something like:
BOOL flipped = [self.view isInterfaceFlipped];

Fullscreen UIView will not animate its appearance

I need some help with some basic transition work. I think I don't understand this conceptually.
I load a main view which loads a 'log in screen' in its viewDidLoad.
The 'log in screen' is a custom xib + custom view controller.
It is loaded in the following way:
ISSplashScreenViewController* splashScreenController = [[ISSplashScreenViewController alloc] initWithNibName:#"ISSplashScreen" bundle:nil];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:splashScreenController.view cache:YES];
[UIView setAnimationDuration: 1.5];
[splashScreenController viewWillAppear:YES];
[self.view addSubview:splashScreenController.view];
[splashScreenController viewDidAppear:YES];
[UIView commitAnimations];
All I can see is the status bar animating (and I think this is because it is hidden in the main window but I call for it in the log in screen's viewDidLoad).
The body of the log in screen 'just appears'.
I was wondering if someone could explain why this isn't working and perhaps suggest what i could do to make it work. I think I have to remove the main view from the application's sub views and then load the log in view.
I tried this also, but it doesnt work. The main view just sits there.
[splashScreenController viewWillAppear:YES];
[self.view.superview addSubview:splashScreenController.view];
[self.view.superview bringSubviewToFront:splashScreenController.view];
[self.view removeFromSuperview];
[splashScreenController viewDidAppear:YES];
Any help is much appreciated,
Thanks
Try calling -setAnimationTransition:forView:cache: with self.view rather than the splash-screen controller’s view.

Question about multiple views in iPhone App Development

Is it possible to create a viewcontroller that could handle 5 views?
And is it possible to implement a different button on every view to make a transition to root view?
So my idea of the app is when I load it it takes me to main window, and on that window there will be 5 button that will take me to the 5 views, and after I'm in that view, among other buttons there will be just one button that will take me only to the MainView.
Let's say that some of those 5 views will be Options, Score, Statistics, something like that.
If it is possible to make an app like that using so much views, is it a good approach?
This would be possible, but from what you describe, it does not sound like a good idea. I would suggest instead making a Tab Bar app, and having a separate view controller for each of your 5 views.
If you do not want to make a tab bar app, you can certainly do what you describe, but I would recommend having a separate view controller instance for each view. You could have your 5 buttons in your main view, and each button could push a modal view with no animation. You could then add whatever transition animation you want. In your modal view, you could have a button that pops the modal view.
In your main view controller, you would do this:
- (IBAction)button1Click {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES];
UIViewController *newController = [[UIViewController alloc] initWithNibName:#"View1" bundle:nil];
[self presentModalViewController:newController animated:NO];
[newController release];
[UIView commitAnimations];
}
And in your view 1 controller:
- (IBAction)backToMainClick {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.view cache:YES];
[self dismissModalViewControllerAnimated:NO];
[UIView commitAnimations];
}

Toggling Views EXC_BAD_ACCESS

I have a UIView in my class (besides the original view) made in interface builder.
#interface TimeLineGrid : UIViewController {
UIView *toggleView;
}
#property (nonatomic, retain) IBOutlet UIView *toggleView;
I have synthesized it as well. I have implemented a swipe gesture so that when swiped up, the toggle view is added and when swiped down the toggle view is removed.
-(void)swipedUp {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2.0f];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:NO];
[self.view addSubview:self.toggleView];
[UIView commitAnimations];
}
-(void)swipedDown {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2.0f];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO];
[self.toggleView removeFromSuperview];
[UIView commitAnimations];
}
It works fine when I swipe up once and when I swipe down after that. But when i swipe up once again, it crashes with EXC_BAD_ACCESS error. I know this has something to do with the retain count increasing when I addSubview and reducing when I removeSubview. Can someone shed more light on this? How do I achieve this toggle?
EDIT:
My view hierarchy is as follows:
->UIView (toggleView)
->UIView (mainView to which toggleView is being added)
-->UIToolBar
Most likely, the view is being released when you call [self.toggleView removeFromSuperview];. I recommend that you restructure your code a little.
Since you are creating the view in IB, declare it in the header file as
IBOutlet UIView *toggleView;
Do not include the property call or the synthesize. Since you are not setting or getting the toggleView, just refer to it by the pointer.
In the implementation, set the pointer to nil in viewDidUnload and release it in dealloc. Then, adjust your toggle methods as follows:
-(void)swipedUp {
if (![toggleView superview]) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2.0f];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:NO];
[self.view addSubview:toggleView];
[UIView commitAnimations];
}
}
-(void)swipedDown {
if ([toggleView superview]) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2.0f];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO];
[toggleView removeFromSuperview];
[UIView commitAnimations];
}
}
Here, the if clause will catch the event that the user swipes up twice in a row and not respond to the second swipe. Notice also that this uses toggleView in place of self.toggleView.
This should resolve the problem.
Could you please apply such changes and tell which UIView is exactly has proble.
Open XCode/Product/Edit Scheme...
Move to Environment Variables and then click the plus to add variable
Add variable NSZombieEnables - value: YES
Add variable MallocStackLoggingNoCompact - value: 1
After starting the application, you will see, which exactly object was disposed, when you call it.
I suggest making the views you want to show/hide, be both subviews of a container view. Then, in your animation block you first remove a view that dissapears and add the view that you want to show. For example:
#interface TimeLineGrid : UIViewController {
// declare the views you want to flip between
UIView *mainView;
UIView *toggleView;
}
#property (nonatomic, retain) IBOutlet UIView *mainView;
#property (nonatomic, retain) IBOutlet UIView *toggleView;
In your implementation:
// self.view is the container view (an instance of UIView).
// Initially, self.mainView is a subview of self.view
-(void)transitionFromView:(UIView *)fromView toView:(UIView *)toView withAnimation:(UIViewAnimationTransition)animation {
if ([toView superview]) {
// toView already shown
return;
}
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2.0f];
[UIView setAnimationTransition:animation forView:self.view cache:NO];
[self.view removeFromSuperview:fromView];
[self.view addSubview:toView];
[UIView commitAnimations];
}
-(void)swipedUp {
[self transitionFromView:self.mainView
toView:self.toggleView
withAnimation:UIViewAnimationTransitionFlipFromLeft];
}
-(void)swipedDown {
[self transitionFromView:self.toggleView
toView:self.mainView
withAnimation:UIViewAnimationTransitionFlipFromRight];
}
Note however, that use of the method setAnimationTransition:forView:cache: is now discouraged. Apple recommends using the UIView transitionWithView:duration:options:animations:completion: method (see the UIView reference).
I hope this helps!
I have made an application containing UITabbar and I got the same behavior but with UIButton.
That happens when you dont release the object on which you call removeFromSuperview, I have the same effect when I was removing a UIButton from my viewControllers view.
In my case I could still see the button and if I click on it, I get an exception like unrecognized selector send to object of type NSCFString.
But if I change the tab then return to my view controller where the button was showing previously after removing it from my view, then it was gone.
So my conclusion is that if you dont release the object on which your are calling removeFromSuperview then the app will show some unexpected behavior if you have the object as an instance variable of your class and added it to the view programmatically by addSubView method.
What are your options:-
You can call removeFromSuperview on a uiview or its subclass objects and call release on it or make it nil.
You can hide or unhide those objects using hidden property instead of removing them from superview.
(I haven't tried it exactly)You can create a UIView object in your class implementation and then add it as a subview and then assign it to your instance variable your class using dot operator and then release the previously created UIView object.
I dont know how my answer might help you but I think its good to share your experience with others.

View from the second tab in the background at transition between two views at the first tab (and not a color as is should)

I have an tabbar-application with four tabs. Every tab loades an nib with its viewcontroller.
In my first nib i have two views. In the first view (placeholder) is a button to switch to the second view (view1) and reverse (With an Boolean to see if the second view is on top or not).
-(IBAction)transitionFlip {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.5];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
if (view1OnTop) {
[view1 removeFromSuperview];
view1OnTop = NO;
}
else {
[placeholder addSubview:view1];
view1OnTop = YES;
}
[UIView commitAnimations];
}
The Problem:
When i click on the button it works fine. But the Second-Tabbar Nib is on the animation-background?
When i click on the Second-Tabbar and go back to the first, then the animation-background is white (as it should).
In the Main Appdelegate i have only added two Controllers:
[window addSubview:navigationController.view];
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
Any ideas?
The problem is likely caused by adding both navigationController.view and tabBarController.view as subviews of UIWindow. Instead of this view hierarchy:
UIWindow -> [UITabBarController -> [view, view, ...], UINavigationController -> view]
try adding only tabBarController's view to the window, and letting it manage separate UINavigationControllers for each tab:
UIWindow -> UITabBarController -> [UINavigationController -> view, UINavigationController -> view, ...]