Hiding an animated modal UIView? - objective-c

I need to present and then dismiss a UITableView modally. It should animate in from top to button. But it should not cover the whole screen, it will slide in from under navigation bar and stop before it reaches the tabbar.
So i can't use the presentViewController:animated:completion: for its view controller.
I need to manipulate it as part of a view hierarchy. The question is, where should this table view be when it is not visible. Where will I animate it from?

You could put the UITableView inside a UIView and use animateWithDuration. For example (using some made up dimensions):
[subMenuView setFrame:CGRectMake(5,-400, 310, 400)];
[UIView animateWithDuration:0.8f
delay:0.0f
options:UIViewAnimationOptionTransitionCurlDown
animations:^{
[subMenuView setFrame:CGRectMake(5,0,310,400)];
}
completion:^ (BOOL finished)
{
if (finished)
{
//animation has finished, you can do something here, even another nested animation
}
}];
If you want to then slide it back up, do the opposite...

Related

Smoother transition from one UIView to another UIView

I have a UIViewController which has multiple subviews. Each subview is a UIView subclass, and I want to switch between views by tapping the toolbar buttons. I did this by using the animation blocks:
Example:
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[StoreView removeFromSuperview];
[self.view addSubview:HomeView];
}
completion:NULL];
Everything is working fine actually. The problem is the transition is not really smooth. For example, the HomeView has five buttons scattered (as part of the design), and whenever I switch from one view to HomeView, these buttons will come from a corner and rearrange itself after the transition, which is not exactly beautiful to look at.
So how will I make these buttons stay in place?
When doing animations with complex subviews you can sometimes get undesirable results as you are experiencing. Not only can some oddities appear, but they are sometimes costly depending on the complexity of the view structure. One suggestion I would make is instead of animating the complex views themselves, you could render the views to a graphics context and animate the resulting image in a UIImageView, using sleight-of-hand to make it appear that you are animating the view hierarchy. In this effect, you avoid doing what amounts to a complex transform on the HomeView and StoreView and instead do simple flip with UIImageView instances. Consider the following example code:
UIImageView *storeImage = // pointer to the image rendered to a graphics context
UIImageView *homeImage = // pointer to the image rendered to a graphics context
[self.view addSubview:storeImage];
[storeView removeFromSuperview];
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[storeImage removeFromSuperview];
[self.view addSubview:homeImage];
}
completion:^(BOOL finished) {
[self.view addSubview:homeView];
[homeImage removeFromSuperview];
}];

Fade UIView and Switch UIView

This is how I switch from one UIView to another UIView: self.view = MyView;
How would I fade out a view to my MySecondView?
You can use UIView's build in transition code to cross dissolve between them.
[UIView transitionFromView:self.view toView:MySecondView duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve completion:^(BOOL finished) {
// What to do when its finished.
}];
You can also use the regular animation options with something like this. I haven't tested this code as I'm not in front of Xcode but I use it all the time for labels and things without default animations.
[UIView animateWithDuration:0.25 animations:^{
[self.view setAlpha:0.0];
self.view = mySecondView;
[self.view setAlpha:1.0];
}];
Please note that it's not a good idea to do things like self.view = MyView to change screens. By the time you get to a few screens, your viewController will be filled with spaghetti code. You should consider presenting new view controllers that manage their views. One way you can do fade is as follows:
Fade the current view to black (with animation)
In the view controller that you are going to push use viewWillAppear to fade the view to black as well
Push/Present the view controller without animations.
Now use the viewDidAppear method of the newly presented view controller to fade in the view (with animation).

Why does view draw under the task bar after a custom scale and flip animation?

Same code as in a previous question, but a different issue.
I've created a custom animation to add a view controller to a UINavigationController. This code scales a view to 80% the original size, then flips it, then scales it back up to its original size:
[UIView animateWithDuration:scaleDuration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
// Scale the controllers' views down.
self.view.transform = CGAffineTransformScale(self.view.transform, 0.8, 0.8);
} completion:^(BOOL finished) {
// Transition to the new view and push on the new view controller.
[UIView transitionWithView:self.view duration:1 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionTransitionFlipFromLeft animations:^{
[self pushViewController:viewController animated:NO];
} completion:^(BOOL finished) {
[UIView animateWithDuration:scaleDuration delay:0 options:UIViewAnimationOptionCurveLinear animations:
^{
// Scale back to the original size.
self.view.transform = CGAffineTransformScale(self.view.transform, 1.25, 1.25);
} completion:nil];
}];
}];
The issue is that, when the animation completes, the new view is displayed very nicely, except that it is drawn under the task bar. That is, it draws in at screen origin 0,0, rather than 0,20. The "Status Bar" option is set in IB (to "Black"), and, naturally, this does not happen if I use a standard UINavigationController push animation, only my custom one. If I rotate the device after the animation, the redraw on rotation moves it to the proper place. But how do I get it to do that in the first place?
As an added wrinkle, it does not draw under the task bar if I move the pushViewController:animated: call a line down to the completion: block (though then the view appears to flip to itself and then suddenly show the new view, of course).
I found the only work around so far is hide the navigationbar and then show it.
after you set your transform, add following 2 lines:
[self setNavigationBarHidden:YES];
[self setNavigationBarHidden:NO];
It's ugly but works, I am also looking for a better solution.
note: layoutsubview, setNeedsLayout won't work.

I would like to implement a half UITableView half MapView UIView with a button in the middle

Well, this is what I want to do in my app: I would like to implment a UIView with a map on the top half of the screen and a tableview on the other half with two buttons in the middle. If I press one of the buttons the map will get fullscreen and if I press the other one the tableView will fit all the screen.
Any suggestion?
In one view controller like a UINavigationController create an MKMapView with a frame the size of the top half of the view and add it as subview of your view controller. Then I would create a UIToolbar to hold your buttons and make the top of it's frame line up with bottom of the MKMapView. Finally create a UITableView with it's frame just below the others (make sure you hook up it's delegates).
Then assign the target of your UIBarButtonItem that makes the map go fullscreen to a method that animates the frames of all three views like this:
[UIView animateWithDuration:0.24
delay:0.0
options:UIViewAnimationCurveEaseOut
animations:(void (^)(void)) ^{
self.toolbar.frame = CGRectMake(0, MAP_HEIGHT_FULLSCREEN, 320, TOOLBAR_HEIGHT);
self.mapView.frame = CGRectMake(0,0,320,MAP_HEIGHT_FULLSCREEN);
self.tableView.frame = CGRectMake(0, MAP_HEIGHT_FULLSCREEN+TOOLBAR_HEIGHT, 320, MAP_HEIGHT_FULLSCREEN-MAP_HEIGHT);
}
completion:^ (BOOL finished){}
];
Create both views how you are planning, On one button click, change the frame of one view to fit the full screen, if you click the other button, do the same thing to the other view.

How to apply flip Horizontal transition to subview without effecting to superview

I have a superview and I've added a subview on superview and added a UIbutton on the subview.My requirement is when I click on UIbutton the flipHorizontal Transition, How will this be applied to subview(Nothing but UIbutton) without effecting to superview(means superview is stable one)?
[UIView transitionFromView:view1 toView:view2
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
completion:^(BOOL finished){
/* do something on animation completion */
}];
Make sure you replace view1 with the name of your button you want to flip, and view2 with the view you want the button to be replaced with. You can just put your Button for both of them so it will flip around with no side effects if you like.