my app is navigation based, i am adding a child view controller to one of my screens like so :
[self addChildViewController:_settingsVc];
[_settingsVc didMoveToParentViewController:self];
[self.view addSubview:_settingsVc.view];
[UIView transitionFromView:self.view toView:_settingsVc.view
duration:0.6
options:UIViewAnimationOptionTransitionFlipFromLeft
completion:^(BOOL finished) {
_header_view.header_title.text = #"Settings";
}];
the view and animation shows great! and when i am returning like so from the presented child view controller :
[UIView transitionFromView:_settingsVc.view toView:self.view
duration:0.6
options:UIViewAnimationOptionTransitionFlipFromRight
completion:^(BOOL finished) {
_header_view.header_title.text = #"Friends Locator";
}];
i goes well too... the problem is if i am entering to the child view controller and hit the back button of the UINavigationBar then i can see the bar slides out and i got black screen.
how can i manage this?
The back button is do UINavigationController pop animation. You can try add a leftBarButtonItem that set a customView which is a UIButton, and add your own back animation in the button click event.
Related
I have a problem :D.
I'm currently using a SplitViewController. At the start I want to hide the TableViewController in the MasterView. So i decided to add a SubView in the Storyboard into the tableView, where a little label will be shown.
So after I make my choice in the DetailView and click the Button I want to hide the subView and want to show the tableView. That all with animations.
So here is my Code:
In the TestTableViewController.m
-(void)AnimateView{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.1];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
fixedView.frame=CGRectMake(-500, 0,0,0);
[UIView commitAnimations];
NSLog(#"test");
And in the TestDetailViewController.m
- (IBAction)attractionButton:(UIButton *)sender
{
TestTableViewController *testTableViewController = [[TestTableViewController alloc]init];
[testTableViewController AnimateView];
}
I get the NSLog "test" but the Animation is not working.
fixedView is my Subview and I drag it to the header file so it's an IBOutlet.
Thank you so far.
So you seem to instantiate a new ViewController and trying to perform this animation straight away:
TestTableViewController *testTableViewController = [[TestTableViewController alloc]init];
[testTableViewController AnimateView];
The problem is that you don't even present that view controller (its view is not on screen anywhere) so it's normal you don't see any animation.
From my understanding you already have another instance of this view controller presented on screen (am I right?) - so that is the one that you need to use. Pass its pointer to TestDetailViewController in some way (e.g. a property) and then use that object to call your animation method.
PS. I would recommend naming all your methods starting with a lower case letter ;)
The problem is, you are not referencing the same master view controller in your details view controller.
You are creating another one in your IBAction.
In order to get a hold of your (the "original" one) master view controller, do this in your detail view controller:
Create a ivar:
TestTableViewController *masterViewController;
And then to reference it:
masterViewController = (TestTableViewController*)[[[self.splitViewController.viewControllers lastObject] viewControllers] objectAtIndex:0];
For example:
- (IBAction)attractionButton:(UIButton *)sender
{
masterViewController = (TestTableViewController*)[[[self.splitViewController.viewControllers lastObject] viewControllers] objectAtIndex:0];
[masterViewController AnimateView];
}
And finally in your AnimateView method, make change to the following:
[UIView animateWithDuration:0.1f animations:^
{
fixedView.frame = CGRectMake(-500, 0, 0, 0);
}
completion:nil];
Hope this helps.
What you could try is this:
[UIView animateWithDuration:0.15f animations:^{
fixedView.frame=CGRectMake(-500, 0,0,0);
}completion:^(BOOL finished){
}];
Are you sure you can call [UIView beginAnimations: ....] without a first argument?
I am developing iPad application using UISplitViewController. I want to show/hide Master View Controller on demand. I have seen How to hide & unhide Master View Controller in SplitView Controller and Animate visibility of master detail controller of UISplitViewController, so I came up with something like this:
I have hideMasterView BOOL variable in my UISplitViewControllerDelegate and when I want to show/hide Master View I call:
hideMasterView = !hideMasterView;
[UIView animateWithDuration:0.25
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[self.splitViewController willAnimateRotationToInterfaceOrientation:self.interfaceOrientation duration:0];
[self.splitViewController willRotateToInterfaceOrientation:self.interfaceOrientation duration:0];
[self.splitViewController didRotateFromInterfaceOrientation:self.interfaceOrientation];
[self.splitViewController viewWillLayoutSubviews];
[self.splitViewController.view layoutSubviews];
}
completion:^(BOOL finished) {}];
And my delegate has method:
- (BOOL)splitViewController:(UISplitViewController *)svc
shouldHideViewController:(UIViewController *)vc
inOrientation:(UIInterfaceOrientation)orientation{
return hideMasterView;
}
It works, but animation is not quite smooth. On hide everything works fine, but when Master View is being shown, Detail View is resized before sliding, leaving blank gray space on right and sliding on it afterwards.
How to fix this animation?
I have a button in my main view controller that pushes a navigation controller with an embedded view controller using a segue.
When the new view controller is presented, the navigation bar on it briefly appears under the status bar. (The status bar is not hidden.) The contents (which are relative to the top layout guide) are in the correct location. As soon as the animation is complete, it fixes itself.
When the view is dismissed again, the same thing happens: the main view controller briefly overwrites the status bar. For the main view controller, this is a little more significant as it's based on a UITableViewController; the entire table jumps. Again, when the animation is complete the view controller fixes itself.
I've tried turning off translucency on the navigation bar, but it only makes the problem more obvious. All of this works as expected on iOS 6.
I've uploaded a minimalist test case here: https://github.com/tewha/FlipTest
Another simple trick is do this:
In the MasterViewController
When is preparing for Segue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
[UIView transitionWithView:self.navigationController.view
duration:0.75
options:UIViewAnimationOptionTransitionFlipFromRight
animations:nil
completion:nil];
}
And when Unwind the AboutViewController
- (IBAction)aboutUnwind:(UIStoryboardSegue *)segue {
[UIView transitionWithView:((UIViewController *)segue.sourceViewController).view
duration:0.75
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:nil
completion:nil];
}
This is a bug in the layout system of iOS7. I found that reducing the height of the navigation controller's view (not the pushed view controller's!) by the status bar height and placing it in y = status bar height will help a lot, but there will still be a small flicker where the status bar "merges" with the navigation controller.
As a side not, see if the bug still exists in iOS7.1b1.
There is a Problem in the ios 7 with navigation bar ,Navigation bar appear over the views or showing gap between the nav bar and view , You can solved this problem with the help of following code
There has been a new property introduced in iOS 7 that lets you adjust the layout behavior as in previous versions of iOS. this code in your view controller, and you should be good The space your navigation bar takes up should be accounted for automatically
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
Answer obtained from iOS 7 navigation bar jumping / stretching upon viewDidAppear
This is a bug in UK kit. Avoid using the standard methods
'performSegueWithIdentifier' or 'presentViewController'
Here I transition from one controller to another, then transition back in the delegate callback, using UIView transition animations.
-(void)photoButtonPressed:(NSNotification*)notification
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Media"
bundle:nil];
UINavigationController *navCon = [storyboard instantiateInitialViewController];
PhotoCaptureViewController *controller = navCon.viewControllers.firstObject;
controller.delegate = self;
CustomTabBarViewController *tabBarController = (CustomTabBarViewController*)self.tabBarController;
[UIView transitionWithView:self.navigationController.view duration:0.75 options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
[tabBarController.parentViewController addChildViewController:navCon];
[tabBarController.parentViewController.view addSubview:navCon.view];
} completion:^(BOOL finished) {
[navCon didMoveToParentViewController:tabBarController.parentViewController];
}];
}
-(void)photoCaptureViewController:(PhotoCaptureViewController *)controller dismissButtonPressed:(UIButton *)dismissButton
{
CustomTabBarViewController *tabBarController = (CustomTabBarViewController*)self.tabBarController;
[UIView transitionFromView:controller.navigationController.view toView:tabBarController.view duration:1 options:UIViewAnimationOptionTransitionFlipFromLeft completion:^(BOOL finished) {
[controller.navigationController willMoveToParentViewController:nil];
[controller.navigationController removeFromParentViewController];
[controller.navigationController.view removeFromSuperview];
}];
}
This is a great read about container views Khanlou's blog post
I have two ViewControllers: A and B. A is a delegate of B. I am presenting B from A and when I dismiss it, I am trying to move the views of A. I have methods set up in the delegate to listen to when B is dismissed to try to move the views. This is what I am using now when B is dismissed, but it doesn't work. How can I get this to work?
[self dismissViewControllerAnimated:YES completion:^{
NSLog(#"view dismissed");
[self moveViews:self];
}];
- (IBAction)moveViews:(id)sender
{
[UIView animateWithDuration:0.5
animations:^{
self.view.center = CGPointMake(160, 250);
//self.tableView.center = CGPointMake(160, -100);
self.addView.center = CGPointMake(160, 240);
}
completion:^(BOOL finished){}];
}
looking at your moveViews method, you aren't moving the views from one view controller to the other. You are moving the position of the view. The problem is that the view controller being dismissed will no longer be a part of the screen, so it wont be visible. My recommendation would be to implement iOS 5 UIViewController containment and add the dismissed view controller as a child view controller of the other view controller. The reason for this is because the information contained on the modal view controller (the controls, target for actions and the model) is a part of the modally presented view controller. Check the documentation for the UIViewController class and the containment mentioned here:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html
I think the problem is, that you call here [self moveViews:self]; the method on the view B.
Have a id (for example named sender ) property in B.
When you make the transition set the sender property in B to A.
Call
[self dismissViewControllerAnimated:YES completion:^{
NSLog(#"view dismissed");
[self.sender performSelector:#selector(moveViews)];
}];
then B will be dismissed and calls method moveViews on A.
In A you have a method
- (void)moveViews
{[UIView animateWithDuration:0.5
animations:^{
self.view.center = CGPointMake(160, 250);
}
];
}
should work, have fun
I built a app with storyboard, with an initial view controller, connected to many subsequent view controllers, connected sequentially, using cross dissolve segue. These work one swipes. All works fine. However, instead of being forced to use the basic segues, I want to have a custom segue that will slide the view controller content on and off the screen, much like the push for navigationControllers, but, being enabled to go left and right depending if one is going forward or backwards in the app.
I have set the segue to custom, and have created and saved a MySegue.h file. HOWEVER, I don't know how to code a custom segue that will slide one viewcontroller off the screen as the other slides on and back and forth as I move between view controllers.
Can anyone please provide me with come coding (it should be easy!) for a custom segue to move from one view controller to the next and back by sliding the screen on and off so I don't have to use the basic cross dissolve or standard flips offered in Xcode 4.2? I would be most grateful.
I was running into the same issue here, but I was using swipe gestures to go from one view controller to the next. Using the storyboard itself to set up segues was working fine, but when I needed a swipe to "go back" to the previous view controller, the animation went from right-to-left, instead of left-to-right. To fix that issue I did the following:
Embedded a Navigation Controller in the root view controller.
Used segues to push new view controllers.
When I wanted to "go back" to the previous view controller, I did not add a segue to the storyboard to push the previous view controller. Instead, I called the Navigation Controller's popViewControllerAnimated method whenever a back swipe occurred.
To create a custom segue that slides view controllers first create a class that extends UIStoryboardSegue, then override the perform selector. I just made something like this and it should work for you too. Here's my code:
#define kAnimationDuration 0.5
#import "CustomSlideSegue.h"
#implementation CustomSlideSegue
- (void)perform
{
UIViewController *sourceViewController = (UIViewController *) self.sourceViewController;
UIViewController *destinationViewController = (UIViewController *) self.destinationViewController;
[sourceViewController.view addSubview:destinationViewController.view];
[destinationViewController.view setFrame:sourceViewController.view.window.frame];
[destinationViewController.view setBounds:sourceViewController.view.bounds];
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if ( !self.slideLeft ) {
[UIView animateWithDuration:kAnimationDuration
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
[destinationViewController.view setCenter:CGPointMake(screenSize.height + screenSize.height/2, screenSize.height/2 - 138)];
[destinationViewController.view setCenter:CGPointMake(screenSize.width/2 + 127, screenSize.height/2 - 138)];
}
completion:^(BOOL finished){
[destinationViewController.view removeFromSuperview];
[sourceViewController presentViewController:destinationViewController animated:NO completion:nil];
}];
} else {
[UIView animateWithDuration:kAnimationDuration
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
[destinationViewController.view setCenter:CGPointMake(-1*screenSize.height/2, screenSize.height/2 - 138)];
[destinationViewController.view setCenter:CGPointMake(screenSize.width/2 + 127, screenSize.height/2 - 138)];
}
completion:^(BOOL finished){
[destinationViewController.view removeFromSuperview];
[sourceViewController presentViewController:destinationViewController animated:NO completion:nil];
}];
}
}
Then when you want to perform the segue use this code:
UIViewController *destination = [self.storyboard instantiateViewControllerWithIdentifier:#"some identifier"];
CustomZoomSegue *segue = [[CustomZoomSegue alloc] initWithIdentifier:#"segue vc identifier" source:self destination:destination];
[self prepareForSegue:segue sender:self];
[segue perform];
The CGPointMake calls are custom to my code (I used landscape orientation) but you should be able to change it to fit your needs. If you need further clarification or have any question let me know and I will try to answer.
NOTE: I use storyboards with no segue lines between the view controllers.
Why not just use a UINavigationController? This seems to be exactly what they're designed for.