2013-11-29 20 views
-1

我有一個可以在ios7中正常工作的幻燈片segue,但是在ios6的動畫定位中有一個跳轉。差異似乎是由於ios6上的狀態欄 - 因爲位置的差異與狀態欄高度相匹配。我可以把圖層的位置搞定,以使其工作,但它感覺不舒服 - 我想了解它爲什麼會發生。ios6上的動畫未對齊

暫停動畫和檢查上iOS6的層層次結構給出了這樣的:

<UIWindow: [The root window] 
    frame = (0 0; 320 568); 
    layer = <UIWindowLayer: 0x8127b50; frame = (0 0; 320 568)> 
> 
    | <UIView: [The root view] 
    |  frame = (0 0; 320 548); 
    |  layer = <CALayer: frame = (0 0; 320 548)> 
    | > 
    | | <CALayer: frame = (0 0; 320 548)> [Animation is happening in this layer] 
    | | | <CALayer: frame = (1 0; 320, 548)> 
    | | | <CALayer: frame = (321 0; 320 548)> 

當動畫完成的層的層次結構是這樣的:

<UIWindow: [The root window] 
    frame = (0 0; 320 568); 
    layer = <UIWindowLayer: frame = (0 0; 320 568)> 
> 
    | <UIView: [The root view] 
    |  frame = (0 20; 320 548); 
    |  layer = <CALayer: frame = (0 20; 320 548)> 
    | > 

在ios7所述非動畫根視圖層的位置只是(0 0 ...),而不是(0 20 ...),我認爲這只是狀態欄的透明度。

所以有些東西在ios6上移動根視圖層的位置,但我不知道爲什麼。我可能在做一些愚蠢的事情,但我無法看到它。任何指針將不勝感激。

#import "ANBSlideSegue.h" 
#import <Foundation/Foundation.h> 
#import <CoreGraphics/CoreGraphics.h> 


@implementation ANBSlideSegue 


-(UIImage*) screenShot:(UIView*)aView color:(UIColor*)color { 

    //This will only work on the main thread, so lets assert that here.. 
    NSAssert([NSThread isMainThread], @"screenShot only works on the main thread..."); 

    //This should no longer be needed - we set the view frames on construction. 
    //Since this may not have been layed out .. we force a layout here. 
    CGRect frame = (CGRect){.size = hostView.frame.size}; 

    CGRect imageFrame = frame; 

    aView.frame = frame; 

    [aView layoutIfNeeded]; 

    UIGraphicsBeginImageContextWithOptions(imageFrame.size, NO, 0.0); 

    CGContextSaveGState(UIGraphicsGetCurrentContext()); 

    //Adjust for the frame 
    CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 
         aView.frame.origin.x, 
         aView.frame.origin.y); 


    [aView.layer renderInContext:UIGraphicsGetCurrentContext()]; 

    CGContextRestoreGState(UIGraphicsGetCurrentContext()); 
    CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), color.CGColor); 
    CGContextFillRect(UIGraphicsGetCurrentContext(), imageFrame); 
    UIImage* image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    return image; 
} 

-(CALayer*) createLayerFromView:(UIView*) aView transform:(CATransform3D) transform image:(UIImage*) shot { 
    CALayer* imageLayer = [CALayer layer]; 
    imageLayer.anchorPoint = CGPointMake(1.0f, 1.0f); 
    imageLayer.frame = (CGRect){.size = hostView.frame.size}; 
    imageLayer.transform = transform; 
    imageLayer.contents = (__bridge id)shot.CGImage; 
    return imageLayer; 
} 

-(void) animationDidStart:(CAAnimation *)anim { 
} 

-(void) animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 
    [transformationLayer removeAnimationForKey:@"TransitionViewAnimation"]; 
    [transformationLayer removeFromSuperlayer]; 

    UIViewController * parent = ((UIViewController *)self.sourceViewController).presentingViewController; 
    if(parent) { 
    [self.sourceViewController dismissViewControllerAnimated:NO completion:NULL]; 
    [parent presentViewController:self.destinationViewController animated:NO completion:NULL]; 
    } else if(self.sourceViewController == UIApplication.sharedApplication.keyWindow.rootViewController) { 
    UIApplication.sharedApplication.keyWindow.rootViewController = self.destinationViewController; 
    } else { 
    NSLog(@"Error performing finalization of segue!"); 
    } 
} 

-(void)animateWithDuration:(CGFloat) aDuration { 

    CGFloat width = hostView.frame.size.width; 
    CGFloat height = hostView.frame.size.height; 
    float multiplier = _slideLeft ? -1.0f : 1.0f; 

    CABasicAnimation *translation = nil; 


    translation = [CABasicAnimation animationWithKeyPath:@"sublayerTransform.translation.x"]; 
    translation.toValue = [NSNumber numberWithFloat:multiplier * width]; 

    translation.fillMode = kCAFillModeForwards; 
    translation.removedOnCompletion = NO; 
    translation.delegate = self; 
    translation.duration = aDuration; 

    [CATransaction flush]; 
    [transformationLayer addAnimation:translation forKey:@"TransitionViewAnimation"]; 
} 

- (void) constructTranslationLayer 
{ 

    UIViewController *source = (UIViewController *) self.sourceViewController; 
    UIViewController *dest = (UIViewController *) self.destinationViewController; 

    hostView = source.view; 

    //For rotated views we need to hack in the transformations and size to match too.. 
    dest.view.transform = source.view.transform; 
    dest.view.frame = source.view.frame; 

    UIImage * sourceShot = [self screenShot:source.view color:[UIColor.blackColor colorWithAlphaComponent:0.2f]]; 
    UIImage * destShot = [self screenShot:dest.view color:UIColor.clearColor]; 

    dest.view.layer.borderWidth=2.0f; dest.view.layer.borderColor= [[UIColor whiteColor] CGColor]; 


    transformationLayer = [CALayer layer]; 
    transformationLayer.borderWidth=2.0f; transformationLayer.borderColor= [[UIColor redColor] CGColor]; 

    transformationLayer.frame = hostView.bounds; 
    transformationLayer.anchorPoint = CGPointMake(0.5f, 0.5f); 
    CATransform3D sublayerTransform = CATransform3DIdentity; 
    [transformationLayer setSublayerTransform:sublayerTransform]; 
    [hostView.layer addSublayer:transformationLayer]; 

    CATransform3D transform = CATransform3DMakeTranslation(1.0, 0, 0); 

    CALayer * sourceLayer = [self createLayerFromView:source.view transform:transform image:sourceShot ]; 

    [transformationLayer addSublayer:sourceLayer]; 

    //If we're rotated we need to adjust the direction 
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; 

    CGFloat scale = (_slideLeft)?1.0:-1.0; 

    transform = CATransform3DTranslate(transform, scale*hostView.frame.size.width, 0, 0); 

    CALayer * destLayer =[self createLayerFromView:dest.view transform:transform image:destShot]; 
    [transformationLayer addSublayer:destLayer]; 

} 

- (void)perform { 
    [self constructTranslationLayer]; 
    [self animateWithDuration:3.0f]; 
} 

@end 

回答

0

原來的問題是在屏幕截圖功能,將其取截圖,但不能恢復它之前調整該層的幀一些愚蠢。結果發現對框架的更改不再是必需的,所以功能看起來像這樣:

-(UIImage*) screenShot:(UIView*)aView color:(UIColor*)color { 

    //Since this may not have been layed out .. we force a layout here. 
    [aView layoutIfNeeded]; 

    //This will only work on the main thread, so lets assert that here.. 
    NSAssert([NSThread isMainThread], @"screenShot only works on the main thread..."); 

    CGRect frame = (CGRect){.size = hostView.frame.size}; 

    UIGraphicsBeginImageContextWithOptions(frame.size, NO, 0.0); 

    CGContextSaveGState(UIGraphicsGetCurrentContext()); 
    [aView.layer renderInContext:UIGraphicsGetCurrentContext()]; 
    CGContextRestoreGState(UIGraphicsGetCurrentContext()); 
    CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), color.CGColor); 
    CGContextFillRect(UIGraphicsGetCurrentContext(), frame); 
    UIImage* image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    return image; 
}