The Photo Sharing part is a ViewController I wrote, when I press the right item, the PhotoSharingViewController will appear animatedly.
Here is my code:
PhotoSharingViewController *vc = [[PhotoSharingViewController alloc] init];
[self addChildViewController:vc];
[self.view addSubview:vc.view];
[UIView animateWithDuration:0.3 animations:^{
vc.view.frame = CGRectMake(0, 0, WIDTH, WIDTH * 0.8);
} completion:^(BOOL finished) {
}];
However, I do not think it is a good way. I prefer to "present" the viewController, like UIAlertController, or UIActivityViewController. How could I do that, please?
You want to provide a custom transition. That way, when presentViewController is called, you get to provide the UIPresentationController as well as the animation. You are in complete charge of both where the presented view goes and how it animates to get there.
Related
I just tried my making a custom transition between view controllers. It basically spins the next one into view, and it works. Except that the source view controller flickers briefly back into visibility right as the animation completes, just as the destination view controller achieves its final position.
I'm also getting a warning about Unbalanced calls to begin/end appearance transitions which I'm still working on fixing-- I don't know if they're related.
Does anyone see anything here that jumps out as not quite right that would cause a flicker?
I then just assigned a button to do a custom segue via storyboard editor.
-(void)perform
{
UIViewController *source = self.sourceViewController;
UIViewController *destination = self.destinationViewController;
[source.view addSubview:destination.view];
destination.view.transform = CGAffineTransformMakeRotation(M_PI / 2);
[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationCurveEaseInOut animations:^{
destination.view.transform = CGAffineTransformMakeRotation(0);
}completion:^(BOOL finished){
[destination.view removeFromSuperview];
[source presentViewController:destination animated:NO completion:NULL];
}];
}
Take out the removeFromSuperview.
This is typical question and possibly duplicated, but..
There is iPad app which has UINavigationBar and UITabBar. I have created a button on navigationBar which must show appinfoViewController.
When I present it navigationBar and tabTab are still available to tap. But I would like to show appinfoViewController to full app's main screen size (like modal)
This is my code:
- (void)showInfo
{
AboutViewController *about = [[AboutViewController alloc] init];
[about.view setFrame: self.view.frame];
[about.view setAlpha:0.0];
[UIView animateWithDuration:0.5
delay:0.0
options: UIViewAnimationOptionCurveLinear
animations:^{
[about.view setAlpha:1.0];
[self.view addSubview:about.view];
[self addChildViewController:about];
[about didMoveToParentViewController:self];
}
completion:^(BOOL finished){
}];
}
How to present appinfoViewController to full screen?
May be it's possible to present it modally but without BLACK background?
As suggested in the comments, using
[self presentViewController:about animated:YES completion:nil]
would get rid of the nav bar and the tab bar. If you need to keep them, you need to use
[self.navigationController pushViewController:about animated:YES];
EDIT:
In order to have the user interaction disabled everywhere except for your about view, it's slightly trickier: first off, you need to have all of your UI elements embedded in a view that is not the main view of your presenting view controller.
Let's say you have only a button (the "show about" button), you wouldn't just place it in your main view, but you would use another view (let's call it "outer view") that is just as big as the view controller's view and where you place the button (along with any other ui element you might have). You also need an outlet to this outer view. Then write a method such as:
-(void)userInteractionEnabled:(BOOL)enabled
{
self.navigationController.navigationBar.userInteractionEnabled = enabled;
self.tabBarController.tabBar.userInteractionEnabled = enabled;
self.outerView.userInteractionEnabled = enabled;
}
Alternatively you could simply disable every "interactive" outlet instead of outerView. So if, for example, you have 2 textviews, 3 buttons and one UIPickerView, you would set userInteractionEnabled = enabled for each of those outlets (instead of doing it only for the parent view).
Now, in your showInfo method you can have:
CGRect frame = CGRectMake(50, 50, 200, 200); //Use whatever origin and size you need
about.view.frame = frame;
[self.view addSubview:about.view];
[self userInteractionEnabled:NO]
And in your btnClose method you can just put:
[about.view removeFromSuperview];
[self userInteractionEnabled:YES];
I hope this helps, let me know if this is what you needed!
P.S. Maybe you're already aware of this, but there is a class UIPopoverController, only available for iPad's apps, that would pretty much do all of this for you. You can find a tutorial on how to use it here.
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
AboutViewController *about = (AboutViewController *)[storyBoard instantiateViewControllerWithIdentifier:#"about"];
[self.navigationController pushViewController:about animated:YES];
You can add viewcontroller view layer directly to presenting viewcontroller view.
Code should be look like --
AboutViewController *about = [[AboutViewController alloc] init];
[about.view setFrame: self.view.bound];
[about.view setAlpha:0.0];
[self.view addSubview:about.view];
[UIView animateWithDuration:0.5
delay:0.0
options: UIViewAnimationOptionCurveLinear
animations:^{
[about.view setAlpha:1.0];
}
completion:^(BOOL finished){
}];
I have vc1.view covering the whole screen, and I want to be able to dim vc1.view, and have vc2.view zoom into the whole screen.
I don't have any navigation controller in the app, so what's the best practice to achieve my goal? The solution I'm thinking of is:
Add both vc1.view and vc2.view into a common container view
Use [UIView transitionFromView:vc1.view toView:vc2.view ......]
I dislike the idea of having to add views of different vc into a common container view. Any suggestions? Thanks in advance.
You can use transitionFromView:toView:... without adding the new view to a common container, because that transition method takes care of adding the view. The following worked for me. The code is in the view controller whose view is the "from view". I'm using a cross fade here, but you could change that to any of the other available methods:
-(void)switchViews:(id)sender {
UIWindow *win = self.view.window;
YellowController *yellow = [self.storyboard instantiateViewControllerWithIdentifier:#"Yellow"];
yellow.view.frame = self.view.frame;
[UIView transitionFromView:self.view toView:yellow.view duration:2 options:UIViewAnimationOptionTransitionCrossDissolve completion:^(BOOL finished) {
win.rootViewController = yellow;
}];
}
However, to do a custom transition, you do have to add the new view as a subview of whatever view the "from view" is in (I think). In this example, that is the window's view. This code grows the new view from the center of the old one, while that one fades out. At the end of the transition, the view controller is switched to the one that owns the new view (yellow in this case)
After Edit: I changed this method to use a CGAffineTransform (thanks to jrturton for that suggestion made in an answer to my question):
-(void)switchViews3:(id)sender {
UIWindow *win = self.view.window;
YellowController *yellow = [self.storyboard instantiateViewControllerWithIdentifier:#"Yellow"];
yellow.view.frame = self.view.frame;
yellow.view.transform = CGAffineTransformMakeScale(.1, .1);
[win addSubview:yellow.view];
[UIView animateWithDuration:.6 animations:^{
yellow.view.transform = CGAffineTransformIdentity;
self.view.alpha = 0;
}
completion:^(BOOL finished) {
[self.view removeFromSuperview];
win.rootViewController = yellow;
}];
}
To present from vc1 to vc2 without a navigation controller, use
[vc1 presentViewController:vc2 animated:YES completion:nil];
To change the presenting style, Apple provides a few. You just need to set it before calling the above code:
vc2.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
Here is the list:
typedef enum {
UIModalTransitionStyleCoverVertical = 0,
UIModalTransitionStyleFlipHorizontal,
UIModalTransitionStyleCrossDissolve,
UIModalTransitionStylePartialCurl,
} UIModalTransitionStyle;
How is it possible that I change the transition for presenting a modal view controller. Is it possible that the presenting transition is using the default UIModalTransitionStyle....
UIModalTransitionStyleCoverVertical = 0,
UIModalTransitionStyleFlipHorizontal,
UIModalTransitionStyleCrossDissolve,
UIModalTransitionStylePartialCurl,
but the dismiss transition is using the UIViewAnimationTransitionCurlUp transition. Important is that I don't want to use the UIModalTransitionStylePartialCurl it should be the CurlUp one.
Sadly the following code doesn't work:
[UIView transitionFromView:self.view toView:self.parentViewController.parentViewController.parentViewController.view duration:1.0 options:UIViewAnimationTransitionCurlUp completion:^(BOOL finished) {....}];
Maybe it has something to do that the view controller is displayed in modal mode.
It would be nice if someone can help.
It feels kludgy, but you can do this by animating the transition of adding your destination view controller's view, but on the completion of that, you immediately remove it again and then properly transition to it via the presentViewController (this time without animation, since the visual effect has already been rendered).
I do this in a subclassed custom UIStoryboardSegue (you didn't say NIBs or storyboard, but the concept is the same):
- (void)perform
{
UIViewController *src = self.sourceViewController;
UIViewController *dst = self.destinationViewController;
[UIView transitionWithView:src.navigationController.view
duration:0.75
options:UIViewAnimationOptionTransitionCurlUp | UIViewAnimationOptionCurveEaseInOut
animations:^{
[src.navigationController.view addSubview:dst.view];
}
completion:^(BOOL finished){
[dst.view removeFromSuperview];
[src presentViewController:dst animated:NO completion:nil];
}];
}
Clearly, if your source view controller doesn't have a navigation controller, you would replace those "src.navigationController.view" with just "src.view". But hopefully this gives you the idea.
And, anticipating the logical follow-up question, when dismissing the view controller, I have a button hooked up to an IBAction:
- (IBAction)doneButton:(id)sender
{
[UIView transitionWithView:self.view.superview
duration:0.75
options:UIViewAnimationOptionTransitionCurlDown
animations:^{
[self dismissViewControllerAnimated:NO completion:nil];
}
completion:nil];
}
I'm trying to add subview with UIViewAnimationCurveEaseIn into MyMainView.
I have two UIView in my ViewController.xib file.
There is a one button in MainView , when I clicked that button, I want to call another view with UIViewAnimationCurveEaseIn.
In some of iOS app, the new view appear from the below with slide.
I think that's used with UIViewAnimationCurveEaseIn.
I also want to do like that.
If I'm wrong,please guide me how to do that.
Or where can I read that function?
Try this:
AViewController *aVC = [[AViewController alloc]initWithNibName:#"AViewController" bundle:nil];
//[self.navigationController pushViewController:aVC animated:NO];
[UIView transitionFromView:self.view toView:aVC.view duration:0.5f options:UIViewAnimationCurveEaseIn completion:^(BOOL doneDissolve){
[self.view addSubview:aVC.view];
}];
[aVC release];