-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