推和模型之间的不同介绍

时间:2016-01-18 03:55:08

标签: ios objective-c animation transition

我有自定义转换,我将它应用于符合UIViewControllerTransitioningDelegate协议的ViewController。我的过渡工作正常。但是,当我将UIViewControllerTransitioningDelegate协议更改为UINavigationControllerDelegate协议时,它的工作方式很奇怪。

The function i want to realize

Strange presentation with only one piece of toView

MyTransitioning:

#import "MyTransitioning.h"
#define PARTS_COUNT 4

@interface MyTransitioning()
@property (nonatomic) CGFloat partWidth;
@property (nonatomic) CGFloat partHeight;
@end

@implementation MyTransitioning

-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
    return 1.0;
}

-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    UIViewController* fromCtrl = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController* toCtrl = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView* fromView = fromCtrl.view;
    UIView* toView = toCtrl.view;
    UIView* container = [transitionContext containerView];
    CATransform3D transform = container.layer.transform;
    transform.m34 = -0.01;
    [container.layer setSublayerTransform:transform];

    NSArray<UIView*>* fromViewParts = [self spliteView:fromView];
    NSArray<UIView*>* toViewParts = [self spliteView:toView];
    [self addViews:toViewParts ToContainer:container isFromView:NO];
    [self addViews:fromViewParts ToContainer:container isFromView:YES];
    [fromView removeFromSuperview];


    [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^
    {
        [self strechViews:toViewParts];
        [self compressViews:fromViewParts ToLeft:YES];
    } completion:^(BOOL finished)
    {
        if (!finished)
        {
            NSLog(@"not finish");
        }
        [self removeViewsfromSuper:fromViewParts];
        [self removeViewsfromSuper:toViewParts];
        [container addSubview:toView];
        [transitionContext completeTransition:!transitionContext.transitionWasCancelled];
    }];
}

-(NSArray*)spliteView:(UIView*)view
{
    self.partWidth = view.bounds.size.width / PARTS_COUNT;
    self.partHeight = view.bounds.size.height;
    CGRect region = CGRectMake(0, 0, self.partWidth, self.partHeight);

    NSMutableArray<UIView*>* viewParts = [NSMutableArray array];
    for (int i = 0; i < PARTS_COUNT; i++)
    {
        region.origin.x =self.partWidth * i;
        UIView* partView = [view resizableSnapshotViewFromRect:region afterScreenUpdates:YES withCapInsets:UIEdgeInsetsZero];
        [viewParts addObject:partView];
        partView.frame = region;
    }
    return viewParts;
}

-(void)addViews:(NSArray<UIView*>*)views ToContainer:(UIView*)container isFromView:(BOOL)isFromView
{
    isFromView ? [self strechViews:views] : [self compressViews:views ToLeft:NO];
    for (UIView* view in views)
    {
        [container addSubview:view];
    }
}

-(void)compressViews:(NSArray<UIView*>*)views ToLeft:(BOOL)toLeft
{
    CGFloat x = toLeft ? 0 : self.partWidth * 4;
    int isClockWise = -1;
    CGPoint position = CGPointMake(x, self.partHeight / 2);
    for (UIView* view in views) {
        isClockWise *= -1;
        view.layer.anchorPoint = CGPointMake(0.5 - isClockWise * 0.5, 0.5);
        view.layer.position = position;
        view.layer.transform = CATransform3DMakeRotation(M_PI_2 * isClockWise, 0, 1, 0);
    }
}

-(void)strechViews:(NSArray<UIView*>*)views
{
    int isClockWise = -1;
    for (UIView* view in views)
    {
        isClockWise *= -1;
        view.layer.anchorPoint = CGPointMake(0.5 - isClockWise * 0.5, 0.5);
        NSLog(@"%@",NSStringFromCGPoint(view.layer.anchorPoint));
        CGPoint position = view.layer.position;
        position.x = self.partWidth * [views indexOfObject:view] + (isClockWise == 1 ? 0 : self.partWidth);
        view.layer.position = position;
        view.layer.transform = CATransform3DIdentity;
        NSLog(@"%@",NSStringFromCGRect(view.frame));
    }
}

-(void)removeViewsfromSuper:(NSArray<UIView*>*)views
{
    for (UIView* view in views)
    {
        [view removeFromSuperview];
    }
}

@end

的ViewController:

#import "ViewController.h"
#import "MyTransitioning.h"
#import "SecondController.h"

@interface ViewController ()<UINavigationControllerDelegate>
//@interface ViewController ()<UIViewControllerTransitioningDelegate>
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

//-(id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
//{
//    return [MyTransitioning new];
//}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    self.navigationController.delegate = self;
//    SecondController* ctrl = [segue destinationViewController];
//    ctrl.transitioningDelegate = self;
}

-(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
{
    if (operation == UINavigationControllerOperationPush) {
        return [MyTransitioning new];
    }
    return nil;
}

@end

1 个答案:

答案 0 :(得分:0)

如果您的问题在PresentViewControllerPush之间存在差异,那么pop查看控制器,

  • PushViewController 推送视图控制器是导航控制器的属性。当你想从一个控制器向前移动时,你可以使用它。
  • PopViewController Pop视图控制器也是导航控制器的属性。如果你想在导航堆栈中向后移动,你可以这样做。
  • PresentViewController /模型视图控制器

    当前视图控制器不是导航控制器的属性。要执行push/pop,您的控制器应直接或间接地使用UINavigationController进行子类化。然而,要呈现视图控制器,您不需要引用导航控制器,直接调用[self presentViewController..]