我尝试制作自定义 segue 来模拟来自 iOS6 的旧 segue 推送,因为新的推送 segue 不适用于我的应用程序。
-(void)perform {
UIViewController *sourceViewController = (UIViewController*)[self sourceViewController];
UIViewController *destinationController = (UIViewController*)[self destinationViewController];
CATransition* transition = [CATransition animation];
transition.duration = 1.5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
transition.subtype = kCATransitionFromRight; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
[sourceViewController.navigationController.view.layer addAnimation:transition
forKey:kCATransition];
[sourceViewController.navigationController pushViewController:destinationController animated:NO];
}
一切都嵌入在导航 Controller 中。我已将延伸边缘标记为“在顶部栏下方”和“在底部栏下方”。而且我在两个 View Controller (源和目标)中都有 View 的自定义背景颜色。在这两个 View Controller 之间的过渡期间,导航栏开始在白色和两个 View Controller 的自定义背景颜色之间闪烁。知道为什么吗?
你的代码中的问题是这样的:
当你触发 pushViewController
方法时,sourceViewController
立即从导航堆栈中移除,destinationViewController
出现。
这会导致动画出现问题(即使在 iOS 6 上也存在问题,导致另一个问题,即“黑色渐变”)。
如果您仍想使用 pushViewController
(这更容易,因为您不需要重建导航逻辑),您必须按照 Apple here 的建议进行操作
Regardless of how you perform the animation, at the end of it, you are responsible for installing the destination view controller (and its views) in the right place so that it can handle events. For example, if you were to implement a custom modal transition, you might perform your animations using snapshot images and then at the end call the presentModalViewController:animated: method (with animations disabled) to set up the appropriate modal relationship between the source and destination view controllers.
您应该使用快照。
这里你的 perform 方法更新了:
- (void)perform
{
UIViewController *source = (UIViewController *) self.sourceViewController;
UIViewController *destination = (UIViewController *) self.destinationViewController;
// Swap the snapshot out for the source view controller
UIWindow *window = source.view.window;
UIImageView *screenShot = [[UIImageView alloc] initWithImage:[self screenshot]];
BOOL animsEnabled = [UIView areAnimationsEnabled];
[UIView setAnimationsEnabled:NO];
[window addSubview:screenShot];
[UIView setAnimationsEnabled:animsEnabled];
CATransition* transition = [CATransition animation];
transition.duration = 1.5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
transition.subtype = kCATransitionFromRight; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
[source.navigationController pushViewController:destination animated:NO];
[destination.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[UIView animateWithDuration:1.5f animations:^{
screenShot.frame = CGRectOffset(screenShot.frame, -screenShot.frame.size.width, 0);
} completion:^(BOOL finished) {
[screenShot removeFromSuperview];
}];
}
要做出正确的截图,仅仅使用 renderInContext
方法是不够的,因为半透明条的模糊没有正确管理。
我找到了另一种方法(从 THIS 问题复制和粘贴)
- (UIImage *)screenshot
{
CGSize imageSize = CGSizeZero;
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (UIInterfaceOrientationIsPortrait(orientation)) {
imageSize = [UIScreen mainScreen].bounds.size;
} else {
imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
}
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
CGContextSaveGState(context);
CGContextTranslateCTM(context, window.center.x, window.center.y);
CGContextConcatCTM(context, window.transform);
CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y);
if (orientation == UIInterfaceOrientationLandscapeLeft) {
CGContextRotateCTM(context, M_PI_2);
CGContextTranslateCTM(context, 0, -imageSize.width);
} else if (orientation == UIInterfaceOrientationLandscapeRight) {
CGContextRotateCTM(context, -M_PI_2);
CGContextTranslateCTM(context, -imageSize.height, 0);
} else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
CGContextRotateCTM(context, M_PI);
CGContextTranslateCTM(context, -imageSize.width, -imageSize.height);
}
if ([window respondsToSelectorselector(drawViewHierarchyInRect:afterScreenUpdates]) {
[window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
} else {
[window.layer renderInContext:context];
}
CGContextRestoreGState(context);
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
我附上了一个示例项目,展示了它是如何工作的:Link to sample project
关于ios7 : Custom Push segue pre iOS7 style almost working,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19978130/
欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) | Powered by Discuz! X3.4 |