从我可以收集的内容来看,无法将View Controller动画用作Segue转换。目前,我在现有项目中有一组View Controller动画,可在视图控制器之间创建动画过渡。例如:
模态动画.h文件:
//
// MVModalDismissAnimation.h
//
#import "MVBaseAnimation.h"
@interface MVModalAnimation : MVBaseAnimation
@end
模态动画.m文件:
//
// MVModalDismissAnimation.m
//
#import "MVModalAnimation.h"
@implementation MVModalAnimation {
UIView *_coverView;
NSArray *_constraints;
}
#pragma mark - Animated Transitioning
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
//The view controller's view that is presenting the modal view
UIView *containerView = [transitionContext containerView];
if (self.type == AnimationTypePresent) {
//The modal view itself
UIView *modalView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;
//View to darken the area behind the modal view
if (!_coverView) {
_coverView = [[UIView alloc] initWithFrame:containerView.frame];
_coverView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.6];
_coverView.alpha = 0.0;
} else _coverView.frame = containerView.frame;
[containerView addSubview:_coverView];
//Using autolayout to position the modal view
modalView.translatesAutoresizingMaskIntoConstraints = NO;
[containerView addSubview:modalView];
NSDictionary *views = NSDictionaryOfVariableBindings(containerView, modalView);
_constraints = [[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-30-[modalView]-30-|" options:0 metrics:nil views:views] arrayByAddingObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-30-[modalView]-30-|" options:0 metrics:nil views:views]];
[containerView addConstraints:_constraints];
//Move off of the screen so we can slide it up
CGRect endFrame = modalView.frame;
modalView.frame = CGRectMake(endFrame.origin.x, containerView.frame.size.height, endFrame.size.width, endFrame.size.height);
[containerView bringSubviewToFront:modalView];
//Animate using spring animation
[UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0 usingSpringWithDamping:0.8 initialSpringVelocity:1.0 options:0 animations:^{
modalView.frame = endFrame;
_coverView.alpha = 1.0;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
} else if (self.type == AnimationTypeDismiss) {
//The modal view itself
UIView *modalView = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view;
//Grab a snapshot of the modal view for animating
UIView *snapshot = [modalView snapshotViewAfterScreenUpdates:NO];
snapshot.frame = modalView.frame;
[containerView addSubview:snapshot];
[containerView bringSubviewToFront:snapshot];
[modalView removeFromSuperview];
//Set the snapshot's anchor point for CG transform
CGRect originalFrame = snapshot.frame;
snapshot.layer.anchorPoint = CGPointMake(0.0, 1.0);
snapshot.frame = originalFrame;
//Animate using keyframe animation
[UIView animateKeyframesWithDuration:[self transitionDuration:transitionContext] delay:0.0 options:0 animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.15 animations:^{
//90 degrees (clockwise)
snapshot.transform = CGAffineTransformMakeRotation(M_PI * -1.5);
}];
[UIView addKeyframeWithRelativeStartTime:0.15 relativeDuration:0.10 animations:^{
//180 degrees
snapshot.transform = CGAffineTransformMakeRotation(M_PI * 1.0);
}];
[UIView addKeyframeWithRelativeStartTime:0.25 relativeDuration:0.20 animations:^{
//Swing past, ~225 degrees
snapshot.transform = CGAffineTransformMakeRotation(M_PI * 1.3);
}];
[UIView addKeyframeWithRelativeStartTime:0.45 relativeDuration:0.20 animations:^{
//Swing back, ~140 degrees
snapshot.transform = CGAffineTransformMakeRotation(M_PI * 0.8);
}];
[UIView addKeyframeWithRelativeStartTime:0.65 relativeDuration:0.35 animations:^{
//Spin and fall off the corner
//Fade out the cover view since it is the last step
CGAffineTransform shift = CGAffineTransformMakeTranslation(180.0, 0.0);
CGAffineTransform rotate = CGAffineTransformMakeRotation(M_PI * 0.3);
snapshot.transform = CGAffineTransformConcat(shift, rotate);
_coverView.alpha = 0.0;
}];
} completion:^(BOOL finished) {
[_coverView removeFromSuperview];
[containerView removeConstraints:_constraints];
[transitionContext completeTransition:YES];
}];
}
}
-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
if (self.type == AnimationTypePresent) return 1.0;
else if (self.type == AnimationTypeDismiss) return 1.75;
else return [super transitionDuration:transitionContext];
}
@end
上面从底部向上滑动模态视图控制器。
我现在想将其转换为使用故事板和segues。
我还想要转换其他四种类型的动画,那么是否有一种简单的方法可以让上面的类与segue过渡一起工作?
答案 0 :(得分:3)
我可能会误解你,但这里有一个用自定义segue的例子...
@interface TestSegue : UIStoryboardSegue
@end
@implementation TestSegue
-(void)perform
{
UIView *sv = ((UIViewController *)self.sourceViewController).view;
UIView *dv = ((UIViewController *)self.destinationViewController).view;
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
[window insertSubview:dv aboveSubview:sv];
[dv enterRight:0.1 then:^
{
[self.sourceViewController
presentViewController:self.destinationViewController
animated:NO completion:nil];
}];
}
@end
注意我的日常工作&#34; enterRight:&#34;只是UIView上的一个类别
使用自定义segues的方便教程... http://www.bencz.com/hacks/2014/02/07/custom-ios-segues-in-xcode-5/
我在UIView上的类别示例,它只是视图的动画动画......
请注意,你必须拥有&#34;&#34;&#34;阻止,以便能够在自定义segue中使用它。
注意 - 这里有一个完整的解释,即对于那些不熟悉https://stackoverflow.com/a/20760583/294884的人来说,将块作为属性(注意这是所有目标-c)
-(void)enterRight:(float)delay then:(void(^)(void))after
{
CGPoint moveTo = self.center;
CGPoint moveFrom = self.center;
CGFloat simpleOffscreen = [UIScreen mainScreen].bounds.size.width;
moveFrom.x = moveFrom.x + simpleOffscreen;
self.center = moveFrom;
self.hidden = NO;
[UIView animateWithDuration:0.5
delay:delay
usingSpringWithDamping:0.4
initialSpringVelocity:0.1
options:0
animations:^
{
self.center = moveTo;
}
completion:^(BOOL finished)
{
if (after) after();
}
];
}
在Xcode中单击以添加新文件,然后选择类别。有两个方框
所以,一个类别是&#34; on&#34;一些课。在这种情况下,它是&#34; on&#34; UIView的。在底部框中,输入UIView。
在顶部框中,只需输入一些方便,简短的名称。事实上,使用的名称并不重要。例如,典型的选择是&#34; Utility&#34; &#34;助手&#34; &#34;技巧&#34; &#34;动画及#34;或类似的。
现在转到.h文件并添加它,
-(void)enterRight:(float)delay then:(void(^)(void))after;
现在转到.m文件并添加上面的函数。您现在可以在代码中的任何位置使用该功能。这是使用它的一个例子......
-(void)viewDidLoad
{
[super viewDidLoad];
[PFAnalytics trackEvent:@"harvestFBPage"];
[self.slideOff showMessage:@"Next step..."];
[self.slideOff enterRight:0.0 then:nil];
}
所以,对于任何UIView,你可以去[anyUIView enterRight...];
这很棒。在示例中,self.slideOff是一个UIView。
请注意,在该示例中,之后没有任何事情要做。&#34;这是&#34;之后要做的事情的一个例子&#34;。
-(void)viewDidLoad
{
[super viewDidLoad];
[PFAnalytics trackEvent:@"harvestFBPage"];
[self.slideOff showMessage:@"Next step..."];
[self.slideOff enterRight:0.0 then:^
{
NSLog(@"do this afterwards!");
self.slideOff.alpha = 0.5;
etc;
etc;
}];
}
希望有助于分类。如果你不熟悉block作为objective-c中的参数,请不要忘记去https://stackoverflow.com/a/20760583/294884! (并投票!:))
回到问题和...
不可能在自定义segue中使用任何类型的动画,除非包含的概念&#34;完成后运行此块, &#34;因为你必须发消息presentViewController :(动画:否)仅在你完成时。
这是关键。
希望它有所帮助,对不起,如果我误解了你的问题。
答案 1 :(得分:2)
UIStoryBoardSegue
是一个包装过渡动画并在Storyboards中神奇地显示的对象。 可以在自定义segue中使用自定义视图控制器Transition Animation 。
假设您已经有一个实现UIViewControllerAnimatedTransitioning
协议的自定义动画对象(如上所述),您需要:
创建自定义segue以包装动画师并通过继承UIStoryBoardSegue
@interface MYCustomAnimationSegue : UIStoryboardSegue<UIViewControllerTransitioningDelegate>
@end
实现perform:
方法,将其设置为transitioningdelegate(用于模态转换)或者作为navigationController的委托(用于推送或替换转换)
@implementation MYCustomAnimationSegue
- (void)perform {
UIViewController *sourceVC = (UIViewController *)self.sourceViewController;
UIViewController *destVC = (UIViewController *)self.destinationViewController;
//Set the transitioningdelegate (for a modal transition)
destVC.transitioningDelegate = self;
//strong property, necessary to retain the Segue after perform: is finished
//only needed if you want the customSegue to be the transitioningDelegate
sourceVC.customSegue = self;
//Set the modalPresentationStyle
if (&UITransitionContextFromViewKey) {
//iOS8
destVC.modalPresentationStyle = UIModalPresentationFullScreen;
} else {
//iOS7
destVC.modalPresentationStyle = UIModalPresentationCustom;
}
//Call the presentation
[sourceVC presentViewController:destVC animated:YES completion:^{
//release ourselves again
sourceVC.customSegue = nil;
}];
}
@end
实现UIViewControllerTransitioningDelegate
方法以返回自定义动画对象
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source {
return [[MyCustomAnimator alloc] init];
}
当您从一个视图控制器拖动到另一个视图控制器时,您的自定义segue类现在将显示在Interface Builder中。
在你兴奋之前,有一点需要注意:这只适用于一个方向。为了使其适用于Unwind Segues,您的viewcontroller类需要实现necessary methods。