presentViewController without parent view disappearing - iphone

I have a UIViewController, which on it - I use presentViewController to present a new window:
controller.view.frame = source;
[self presentViewController:controller animated:NO completion:nil];
[UIView animateWithDuration:ANIMATION_NORMAL_DURATION animations:^{
controller.view.frame = target;
}completion:^(BOOL finished) {
}];
When I do that - the parent controller (self) disappears before the new controller (controller) appears. And it makes it ugly.
Is there a better way to implement it?
(I don't use NavigationControler in those ViewContollers)
Thanks.

From iOS7 there is the modalPresentationStyle property.
Set it to one of this options: UIModalPresentationOverFullScreen, UIModalPresentationOverCurrentContext, UIModalPresentationCustom
modalViewController.modalPresentationStyle = UIModalPresentationCustom;

do not present, just add a subview
controller.view.frame = source;
//[self presentViewController:controller animated:NO completion:nil];
[self.view addSubview:controller.view];
[UIView animateWithDuration:ANIMATION_NORMAL_DURATION animations:^{
controller.view.frame = target;
}completion:^(BOOL finished) {
}];

Related

Scrollview didn't scrolling after dismissViewControllerAnimated

I'm calling a view controller from my mainScreen with the following code:
VisualizarFotoViewController *visualizarFoto = [self.storyboard instantiateViewControllerWithIdentifier:#"VisualizarFoto"];
[self presentViewController:visualizarFoto animated:NO completion:^{
[UIImageView animateWithDuration:0.5 animations:^{
visualizarFoto.visualizarFoto.contentMode = UIViewContentModeScaleAspectFit;
visualizarFoto.visualizarFoto.image = _fotoPrincipal.image;
visualizarFoto.viewPrincipal.alpha = 1;
visualizarFoto.telaOrigem = 2;
}];
}];
To come back to the mainScreen I dismiss the view controller with the following code:
[UIImageView animateWithDuration:0.2 animations:^{
_viewPrincipal.alpha = 0;
} completion:^(BOOL finished) {
[self dismissViewControllerAnimated:NO completion:nil];
}];
My issue is that when I come back to the mainScreen, my scrollview doesn't answer to any scrolling gesture. I've tried to use [_scrollView becomeFirstResponder] in viewDidAppear section but with no success.
Do you have any hint to solve this please?
Thanks
If is there someone looking for an answer, this is what I did to solve this issue:
- (void)viewDidLayoutSubviews {
// Define the scrollview size accordingly with the number of pages
[_scrollView setFrame:CGRectMake(0, 43, 320, 450)];
[_scrollView setContentSize:CGSizeMake(320 * 3, 450)];
}

Present Modal View with Animation Effect

In my iPhone App I need to display a modal view with transparent background and it should appear with animation like it is appearing from center of view and its size is increasing.
similar like "drawing something" iPhone App when we click on settings button.
How do I do this?
You can do one of 4 following transition styles:
viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
viewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
viewController.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:viewController animated:YES];
If you want something that is not included in these defaults you are going to have to build your own custom animation for presenting the modal view. Like the following but obviously for the style you want.
UIModalTransitionStyle horizontal movement
Let's say you have a viewController thats called aScoreSheet that you want to present. Try to define this method in the view controller that's going to do the presenting.
-(void) presentTransparentModalViewController: (ScoreSheet *) aViewController
{
scoreSheet = aViewController;
UIView *view = aViewController.view;
view.opaque = NO;
[view.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
UIView *each = obj;
each.opaque = NO;
}];
[self.view addSubview:view];
view.center = CGPointMake(160, 800); //for iPhone
[UIView animateWithDuration:0.9 delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
view.center = CGPointMake(160, 240);
} completion:^(BOOL finished) {
self.view.userInteractionEnabled=YES;
}];
}
and then to dismiss the controller:
-(void) dismissTransparentModalViewControllerAnimated:(BOOL) animated{
if (animated) {
[UIView animateWithDuration:0.4
animations:^{
scoreSheet.view.center = CGPointMake(scoreSheet.view.center.x, scoreSheet.view.center.y + 480);
} completion:^(BOOL finished) {
[scoreSheet.view removeFromSuperview];
scoreSheet = nil;
}];
}
}
Not a full answer, but maybe you can take a look at this open source library:
https://github.com/Split82/HMGLTransitions
It has some custom modal transitions, maybe not exactly the one you are looking for, but you can easily add your transition by subclassing HMGLTransition.
Hope this helps

how to make the viewcontroller rotate when added through appdelegate window

I have added a viewcontroller in the window of appdelegate class like this:
-(void)showSearchView:(BOOL)view
{
if(view)
{
searchViewController = [[SearchView alloc] initWithNibName:#"SearchView" bundle:nil];
CGRect viewFrame=searchViewController.view.frame;
viewFrame.origin.y=-1024;
viewFrame.origin.x=248;
[window addSubview:searchViewController.view];
searchViewController.view.frame = viewFrame;
[UIView beginAnimations:#"UIBase Hidden" context:nil];
[UIView setAnimationDuration:0.5];
searchViewController.view.transform = CGAffineTransformMakeTranslation(0,1024);
[UIView commitAnimations];
}
else
{
[UIView beginAnimations:#"UIBase Shown" context:nil];
[UIView setAnimationDuration:0.5];
searchViewController.view.transform = CGAffineTransformIdentity;
[UIView commitAnimations];
[self performSelector:#selector(doTHis) withObject:nil afterDelay:1];
}
}
This gets called from other classes through this command
[apd showSearchView:YES];
where apd is object of appdelegate class
Everything is working fine till here but when i try to rotate it does not rotate. I have even returnd YES in the following method and still it does not rotate:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
What should be done?
Please remember that UIWindow does not rotate. Perhaps You should add a base view controller and do your rotation.

How to change view on button click in iPhone without navigation controller?

I want to know how to change view on button click in iPhone without navigation controller?
If you're doing this with a UIViewController, you would probably do this like following:
- (IBAction)change {
UIViewController* viewController = [[UIViewController alloc] init];
[self.view addSubView];
// Save the UIViewController somewhere if necessary, otherwise release it
}
Not sure why you don't want to use a UINavigationController though. If it's the navigation bar at the top you don't want to see, there's a property for that so you can hide that bar. Not sure about it's name, probably navigationBarHidden or something like that. You can look that up in the API.
There are many different ways you can do that, and you should possibly provide more information about your app.
A generic way to do it is the following, with animation:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
[vc1 viewWillDisappear:YES];
[vc2 viewWillAppear:YES];
vc1.view.hidden = YES;
vc2.view.hidden = NO;
[vc1 viewDidDisappear:YES];
[vc2 viewDidAppear:YES];
[UIView commitAnimations];
In this case, both views are there, you only hide/show them as you need. Alternatively, you could add/remove the view from their superview:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
[vc1 viewWillDisappear:YES];
[vc2 viewWillAppear:YES];
[vc1 removeFromSuperview];
[masterController.view addSubview:vc2.view;
[vc1 viewDidDisappear:YES];
[vc2 viewDidAppear:YES];
[UIView commitAnimations];
Place this in Button IBAction method
[mCurrentView removeFromSuperview];
[self.view addSubView:mNewView];
Assume you have two view myView1 and myView2 and one button myUIButton in memory
myView1.tag = 1;
myView2.tag = 2;
myUIButton.tag = 1; //Current visible view is myView1
-(void) ButtonCLicked:(id) sender
{
UIButton* myButton = (UIButton*)sender;
if(sender.tag == 1)
{
[myView1 removeFromSuperview];
[self addSubview:myView2]
myButton.tag = myView2.tag;
}
else
{
[myView2 removeFromSuperview];
[self addSubview:myView1]
myButton.tag = myView1.tag;
}
}
You can place two UIView variables in the header file and hide/show one of them or you can make another layer over the existing view like this:
-(IBAction)changeView {
UIView *view = [[UIView alloc] initWithNibName:#"letMeSeeThis" bundle:nil];
[self.view addSubview:view];
}

How to implement UIView transition

I have an app which has a start screen with a start button on it. If you tap that button the view changes and a new view appears, let's call that main view.
The way I implemented it is one view controller per view. Now that I want to add transition animations this implementation causes problems. For example, I want to use the following code:
[UIView transitionFromView:startView toView: mainView duration: 2.0
options: UIViewAnimationOptionTransitionCurlDown completion: NULL];
But this doesn't do anything. Reading the documentation suggests that this only works if the view controller doesn't change. The documentation doesn't have any examples of a curl down transition where the view controllers change so I'm not sure what to do.
When I started writing the app I read the guidelines and they suggested that having one view controller per view is the correct way of doing what I'm doing.
Now what is the correct way to implement a view transition when the view controller changes too? Many thanks for your help!
Edit: I am looking for a solution where the first view controller is destroyed.
It was proposed that you effectively create a view controller, use its view, but then disregard the controller itself. This is not advised. In iOS you want to keep your view controller hierarchy synchronized with your view hierarchy. Any techniques like the one proposed are therefore problematic. (WWDC 2011 session 102, while on a different topic, view controller containment, has a lengthy discussion of the importance of keeping these two hierarchies synchronized.)
The most obvious problem is that certain events, notably rotation events, are not going to transmitted successfully to your new controller and you can get some very strange results. It's also not clear with your code above what happens with the old view that you removed, how you would transition back, how you'd clean up the now unnecessary game controller, what would happen on didReceiveMemoryWarning if you were in the game controller, etc. This just seems to introduce a ton a problems.
The easiest solution is apply standard pushViewController and/or presentViewController calls to go from one view to another, and just animate those transitions. If you have questions about either of those methods, or how to animate within the context of those methods, let me know.
By the way, the root of your question was how to transition between view controllers. Here is a old collection of transitions (some for push transitions, some for modal transition) that I was once playing around with. Maybe there's something here that you could use?
- (void)transitionToNewController
{
MyViewController *controller = [[MyViewController alloc] initWithNibName:#"MyView" bundle:nil];
#if TRANSITIONTYPE == 1
// pushViewController with push/slide from right via CATransition
CATransition* transition = [CATransition animation];
transition.duration = 0.3;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController pushViewController:controller animated:NO];
#endif
#if TRANSITIONTYPE == 2
// pushViewController with flip using UIView begin/commitAnimations
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.75];
[self.navigationController pushViewController:controller animated:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
[UIView commitAnimations];
#endif
#if TRANSITIONTYPE == 3
// pushViewController with flip using animation block
[UIView animateWithDuration:0.5
animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[self.navigationController pushViewController:controller animated:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
}
completion:nil];
#endif
#if TRANSITIONTYPE == 4
// pushViewController with fade via CATransition
CATransition* transition = [CATransition animation];
transition.duration = 0.5;
transition.type = kCATransitionFade;
[self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController pushViewController:controller animated:NO];
#endif
#if TRANSITIONTYPE == 5
// pushViewController with fade via animation block
controller.view.alpha = 0.0f;
[UIView animateWithDuration:0.5
animations:^{
self.view.alpha = 0.0f;
controller.view.alpha = 1.0f;
}
completion:^(BOOL finished){
[self.navigationController pushViewController:controller animated:NO];
self.view.alpha = 1.0f; // reset the src alpha so it's there when you pop your view controller off
}];
#endif
#if TRANSITIONTYPE == 6
// pushViewController Flip using UIView begin/commitAnimations
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.75];
[self.navigationController pushViewController:controller animated:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:[self.self navigationController].view cache:NO];
[UIView commitAnimations];
#endif
#if TRANSITIONTYPE == 7
// pushViewController animation using CGAffine scale to look like we're zooming into the new view
[self.view addSubview:controller.view];
[controller.view setFrame:self.view.window.frame];
[controller.view setTransform:CGAffineTransformMakeScale(0.5,0.5)];
[controller.view setAlpha:1.0];
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationCurveEaseOut
animations:^{
[controller.view setTransform:CGAffineTransformMakeScale(1.0,1.0)];
[controller.view setAlpha:1.0];
}
completion:^(BOOL finished){
[controller.view removeFromSuperview];
[self.navigationController pushViewController:controller animated:NO];
}];
#endif
#if TRANSITIONTYPE == 8
// presentViewController animation with slide from right by using CGAffineTransform
self.view.transform = CGAffineTransformMakeTranslation(0, 0);
controller.view.transform = CGAffineTransformMakeTranslation(self.view.frame.size.width, 0);
[self.view addSubview:controller.view];
[UIView animateWithDuration:4.0
animations:^{
// [self presentViewController:controller animated:NO completion:nil];
self.view.transform = CGAffineTransformMakeTranslation(self.view.frame.size.width, 0);
controller.view.transform = CGAffineTransformMakeTranslation(0, 0);
}
completion:^(BOOL finished){
[controller.view removeFromSuperview];
[self presentViewController:controller animated:NO completion:nil];
}
];
#endif
#if TRANSITIONTYPE == 9
// presentViewController animation with slide from right by just animating frames
float width = self.navigationController.view.frame.size.width;
CGPoint right = controller.view.center;
right.x += width;
controller.view.center = right;
[self.navigationController.view addSubview:controller.view];
[UIView animateWithDuration:0.5
animations:^{
CGPoint left = self.navigationController.view.center;
left.x -= width;
self.navigationController.view.center = left;
}
completion:^(BOOL finished){
[controller.view removeFromSuperview];
[self presentViewController:controller animated:NO completion:nil];
}
];
#endif
#if TRANSITIONTYPE == 10
// presentViewController animation with flipfromright
[UIView animateWithDuration:4.0
delay:0.0
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[self.view addSubview:controller.view];
}
completion:^(BOOL finished){
[controller.view removeFromSuperview];
[self presentViewController:controller animated:NO completion:nil];
}];
#endif
#if TRANSITIONTYPE == 11
// presentViewController with flip using UIView begin/commitAnimations
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.75];
[self presentViewController:controller animated:NO completion:nil];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO];
[UIView commitAnimations];
#endif
#if TRANSITIONTYPE == 13
// pushViewController with flip using animation block with transitionWithView
controller.view.frame = self.view.window.frame;
[UIView transitionWithView:self.view.superview
duration:1.0
options:UIViewAnimationTransitionFlipFromRight
animations:^{
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[self.view.superview addSubview:controller.view];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
}
completion:^(BOOL finished){
[self.navigationController pushViewController:controller
animated:NO];
}];
#endif
}
Okey-doke, I found a neat way to achieve exactly what I want. This code, added in the method where I exchange the old view controller and view with the new one, works great:
GameViewController *game = [[GameViewController alloc] init];
UIView *currentView = [currentViewController view];
// remove the current view and replace with myView1
[currentView removeFromSuperview];
// set up an animation for the transition between the views
CATransition *animation = [CATransition animation];
[animation setDuration:0.5];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromBottom];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[window layer] addAnimation:animation forKey:#"SwitchToView1"];
[self setCurrentViewController: game];
[window addSubview:[currentViewController view]];
[game release];
Many thanks to HERE!!