I have a animated transition set up for my view controller. I have no problem adding a presented view controller onto my current view, but I cannot dismiss the presented view using dismissViewControllerAnimated:completion:
Also, when the presented view is added, it is a tableView, with selectable cells. When a cell is a selected, a new navigation controller is initiated and is placed on top. When i dismiss the navigation controller, going back to the presented view, the presented view has become full screen, instead of where the animation placed it earlier..
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
return 0.5f;
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
// Grab the from and to view controllers from the context
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
// Set our ending frame. We'll modify this later if we have to
CGRect endFrame = CGRectMake(0, 300, 320, 300);
if (self.presenting) {
fromViewController.view.userInteractionEnabled = NO;
[transitionContext.containerView addSubview:fromViewController.view];
[transitionContext.containerView addSubview:toViewController.view];
CGRect startFrame = endFrame;
startFrame.origin.y += 220;
toViewController.view.frame = startFrame;
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
fromViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
toViewController.view.frame = endFrame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
else {
toViewController.view.userInteractionEnabled = YES;
[transitionContext.containerView addSubview:toViewController.view];
[transitionContext.containerView addSubview:fromViewController.view];
endFrame.origin.y += 320;
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
toViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeAutomatic;
fromViewController.view.frame = endFrame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
Here is the code for my presented view Controller:
shadedView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
shadedView.backgroundColor = [UIColor colorWithRed:224.0/255.0 green:224.0/255.0 blue:224.0/255.0 alpha:0.7];
[self.view addSubview:shadedView];
dismiss = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[dismiss addTarget:self action:#selector(removeViewController) forControlEvents:UIControlEventTouchUpInside];
dismiss.backgroundColor = [UIColor clearColor];
[shadedView addSubview:dismiss];
detailTableViewController = [[DetailTableViewController alloc] initWithFlag:DETAIL andQRCode:o_qrcodeId];
//detailTableViewController.tableView.backgroundColor = [UIColor blackColor];
detailTableViewController.transitioningDelegate = self;
detailTableViewController.modalPresentationStyle = UIModalPresentationCustom;
//detailTableViewController.view.layer.cornerRadius = 12.0f;
[self presentViewController:detailTableViewController animated:YES completion:nil];
Related
NSLog(#"started");
[UIView animateWithDuration:2 animations:^{
NSLog(#"inside");
} completion:^(BOOL finished){
NSLog(#"finished");
}];
Here is the output:
2015-09-26 13:17:21.541 Look[9894:1848566] started
2015-09-26 13:17:21.541 Look[9894:1848566] inside
2015-09-26 13:17:21.551 Look[9894:1848566] finished
Note the timestamps are milliseconds apart from "inside" to "finished".'
Here is my full code, with the same result and the animation doesn't run.
This is being done for a custom viewController presentation.
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
// Get the set of relevant objects.
UIView *containerView = [transitionContext containerView];
UIViewController *fromVC = (TJWCameraRollCVC *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
TJWPhotoViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
// Set up some variables for the animation.
CGRect containerFrame = containerView.frame;
CGRect toViewStartFrame = [transitionContext initialFrameForViewController:toVC];
CGRect toViewFinalFrame = [transitionContext finalFrameForViewController:toVC];
CGRect fromViewFinalFrame = [transitionContext finalFrameForViewController:fromVC];
NSMutableArray *oldObjects = [[NSMutableArray alloc] init];
UIImageView *zoomImage;
// Set up the animation parameters.
if (presenting) {
// Modify the frame of the presented view so that it starts
// offscreen at the lower-right corner of the container.
UIImageView *zoomImage = [[UIImageView alloc] initWithImage:toVC.chosenImage];
zoomImage.frame = CGRectMake(toVC.fullScreenOrigin.x, toVC.fullScreenOrigin.y, containerFrame.size.width, containerFrame.size.height);
zoomImage.alpha = 0.2;
zoomImage.transform = CGAffineTransformMakeScale(0.1, 0.1);
[containerView addSubview:zoomImage];
toView.frame = CGRectMake(containerFrame.size.width, containerFrame.size.height, containerFrame.size.width, containerFrame.size.height);
}
else {
// Modify the frame of the dismissed view so it ends in
// the lower-right corner of the container view.
fromViewFinalFrame = CGRectMake(containerFrame.size.width, containerFrame.size.height, toView.frame.size.width, toView.frame.size.height);
}
// Always add the "to" view to the container.
// And it doesn't hurt to set its start frame.
[containerView addSubview:toView];
// Animate using the animator's own duration value.
NSLog(#"started");
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
NSLog(#"inside");
if (presenting) {
NSLog(#"presenting");
// Move the presented view into position.
[zoomImage setFrame:toViewFinalFrame];
[zoomImage setTransform: CGAffineTransformMakeScale(1, 1)];
[zoomImage setAlpha:1];
}
else {
// Move the dismissed view offscreen.
[fromView setFrame:fromViewFinalFrame];
}
} completion:^(BOOL finished){
NSLog(#"finished");
BOOL success = ![transitionContext transitionWasCancelled];
NSLog(#"%d", success);
// After a failed presentation or successful dismissal, remove the view.
if ((presenting && !success) || (!presenting && success)) {
[toView removeFromSuperview];
}
if (presenting && success) {
// toView.frame = containerFrame;
[zoomImage removeFromSuperview];
}
// Notify UIKit that the transition has finished
[transitionContext completeTransition:success];
}];
}
I am implementing a custom transition animation between view controllers, but for some reason my navigation Bar is getting animated along with the transition animation. Is this somehow a auto layout issue? I'm not sure how it would be.
Here is the code I am using to display and dismiss the view controllers with a custom transition.
I would like the navigation bar to not be animated, any ideas as to why this is happening?
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
// Grab the from and to view controllers from the context
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
if (self.presenting) {
fromViewController.view.userInteractionEnabled = NO;
[transitionContext.containerView addSubview:fromViewController.view];
[transitionContext.containerView addSubview:toViewController.view];
int frameHeight = fromViewController.view.frame.size.height;
CGRect startFrame = fromViewController.view.frame;
startFrame.origin.y = frameHeight;
toViewController.view.frame = startFrame;
//create a view with the same background color to cover up background on bounce effect
UIView *bottomCover = [[UIView alloc]initWithFrame:CGRectMake(0, startFrame.size.height-30, startFrame.size.width, 30)];
[bottomCover setBackgroundColor:[UIColor colorWithRed:0.956 green:0.962 blue:0.956 alpha:1]];
[transitionContext.containerView insertSubview:bottomCover belowSubview:toViewController.view];
__block CGRect endFrame = toViewController.view.frame;
[UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0 usingSpringWithDamping:.75 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
endFrame.origin.y = 0;
toViewController.view.frame = endFrame;
} completion:^(BOOL finished) {
[bottomCover removeFromSuperview];
toViewController.view.frame = endFrame;
[transitionContext completeTransition:YES];
}];
}
else {
toViewController.view.userInteractionEnabled = YES;
[transitionContext.containerView addSubview:toViewController.view];
[transitionContext.containerView addSubview:fromViewController.view];
CGRect endFrame = toViewController.view.frame;
endFrame.origin.y = 0;
fromViewController.view.frame = endFrame;
[UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0 usingSpringWithDamping:.9 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
int frameHeight = toViewController.view.frame.size.height;
CGRect startFrame = fromViewController.view.frame;
startFrame.origin.y = frameHeight;
fromViewController.view.frame = startFrame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
//Because there is a bug in Xcode apparently.
[[UIApplication sharedApplication].keyWindow addSubview:toViewController.view];
}];
}
}
i'm trying to present PopUp ViewController with animation, using UIViewcontrollerAnimatedTransitioning. I've created a Modal Segue from TableViewCell to my Viewcontroller
In PopupPresentAnimationController (that implement UIViewcontrollerAnimatedTransitioning) i have
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
[fromViewController addChildViewController:toViewController];
toViewController.view.frame = fromViewController.view.frame;
[fromViewController.view addSubview:toViewController.view];
[toViewController didMoveToParentViewController:fromViewController];
NSTimeInterval duration = [self transitionDuration:transitionContext];
[UIView animateWithDuration:duration delay:0.0 usingSpringWithDamping:0.6 initialSpringVelocity:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
fromViewController.view.alpha = 0.5;
} completion:^(BOOL finished) {
fromViewController.view.alpha = 1.0;
[transitionContext completeTransition:YES];
}];
}
The PopUpViewController have a background black with 50% opacity and, when it appear all "works" but after animation end, the screen become black.
UPDATE 1:
UIViewController *fromViewController =[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *container = [transitionContext containerView];
CGRect initialFrame = toViewController.view.frame;
initialFrame.origin.y = toViewController.view.frame.size.height;
toViewController.view.frame = initialFrame;
[container insertSubview:toViewController.view aboveSubview:fromViewController.view];
NSTimeInterval duration = [self transitionDuration:transitionContext];
[UIView animateWithDuration:duration delay:0 options:0 animations:^{
CGRect newFrame = toViewController.view.frame;
newFrame.origin.y = 0;
toViewController.view.frame = newFrame;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
UPDATE 2
In prepareForSegue i have added the follow line
controller.modalPresentationStyle = UIModalPresentationCustom; // controller is the destination
With this line on, the black is no more black!
The problem you're having is that you are adding your toViewController to the fromViewController. When the animation ends, the toViewController is removed and in turn, so is your fromViewController. The proper way to handle this is to use the container view provided by the context:
UIView *container = [transitionContext containerView];
This is an example of how to do a popup transition:
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *container = [transitionContext containerView];
if (!self.beingDismissed) {
//Make controller hidden so it can slide in
CGRect initialFrame = toViewController.view.frame;
initialFrame.origin.y = toViewController.view.frame.size.height;
toViewController.view.frame = initialFrame;
[container insertSubview:toViewController.view aboveSubview:fromViewController.view];
}
[UIView animateKeyframesWithDuration:0.5 delay:0 options:0 animations:^{
if (!self.beingDismissed) {
//Show view controller
CGRect newFrame = toViewController.view.frame;
newFrame.origin.y = 0;
toViewController.view.frame = newFrame;
} else {
//Hide view controller
CGRect newFrame = fromViewController.view.frame;
newFrame.origin.y = fromViewController.view.frame.size.height;
fromViewController.view.frame = newFrame;
}
} completion:^(BOOL finished) {
[transitionContext completeTransition:finished];
}];
}
I am creating an animation where the current view controller slides down, revealing the new view controller beneath it. I have got this working with the view, but I would like to include the navigation controller in the view sliding down. So instead of a view sliding down with no navigation bar, It would slide down with the navigation bar at the top. How woould I fix this. Here is how I am doing it with the view:
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 5.00;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
[[transitionContext containerView] addSubview:fromViewController.view];
toViewController.view.frame = CGRectMake(0, 0, 320, 568);
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
fromViewController.view.frame = CGRectMake(0, 2000, 320, fromViewController.view.frame.size.height);
toViewController.view.frame = CGRectMake(0, 0, 320, fromViewController.view.frame.size.height);
} completion:^(BOOL finished) {
fromViewController.view.transform = CGAffineTransformIdentity;
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
I am hoping you can help me I am trying to implement a Custom Transition in my app that will display a Custom Modal View Controller. I am able to get the View Controller to appear as expected, however, I cannot get the transition to animate. Any help with this or pointers in the right direction would be greatly appreciated.
Please see my code below:
-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
return 1.0;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
CGRect sourceRect = [transitionContext initialFrameForViewController:fromVC];
fromVC.view.frame = sourceRect;
UIGraphicsBeginImageContextWithOptions(fromVC.view.frame.size, NO, 0);
[fromVC.view drawViewHierarchyInRect:fromVC.view.bounds afterScreenUpdates:YES];
UIImage *fromVCImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIView *container = [transitionContext containerView];
[container setBackgroundColor:[UIColor colorWithPatternImage:fromVCImage]];
[container insertSubview:toVC.view belowSubview:fromVC.view];
CGRect fromVCFrame = fromVC.view.frame;
__block CGRect toVCFrame = toVC.view.frame;
toVCFrame.origin.y = fromVCFrame.origin.y + fromVCFrame.size.height;
[toVC.view setFrame:toVCFrame];
[toVC.view setAlpha:0.0];
[toVC.view setBackgroundColor:[UIColor colorWithPatternImage:fromVCImage]];
[transitionContext finalFrameForViewController:toVC];
//3.Perform the animation...............................
[UIView animateWithDuration:1.0
animations:^{
toVCFrame.origin.y = fromVCFrame.origin.y;
toVC.view.frame = toVCFrame;
[toVC.view setAlpha:1.0];
}
completion:^(BOOL finished) {
//When the animation is completed call completeTransition
[transitionContext completeTransition:YES];
}];
}
Adding Code from View Controller when presentViewController is called via a UITapGestureRecognizer
- (void) onTapGesture:(UITapGestureRecognizer *)recognizer
{
ImagesCollectionViewController *imagesCollectionView = [[Utils getStoryboardForDeviceWithIdentifier:MAIN_STORYBOARD] instantiateViewControllerWithIdentifier:IMAGES_VIEW];
imagesCollectionView.transitioningDelegate = self;
imagesCollectionView.modalTransitionStyle = UIModalPresentationCustom;
[self presentViewController:imagesCollectionView animated:YES completion:^{
}];
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
return self.contentSlideTransitionManager;
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
return self.contentSlideTransitionManager;
}
I'm going to guess that this is your problem:
[container insertSubview:toVC.view belowSubview:fromVC.view];
If toVC.view is below fromVC.view, it is hidden behind it, so you are not seeing what it does.