난 당신이 이런 식으로 뭔가있는 것 같아요 :

가 (. 내가 시뮬레이터에서 "디버그> 느린 애니메이션"켜져)를 그리고 당신은 그림자로 이동하는 방식을 좋아하지 않아 그 새로운 크기. 이 대신 원하는 :

당신은 내 테스트 프로젝트 in this github repository를 찾을 수 있습니다.
애니메이션 매개 변수를 선택하고 표보기의 애니메이션 블록에 애니메이션을 추가하는 것은 까다롭지 만 불가능하지는 않습니다. 가장 까다로운 부분은 음영 처리 된 뷰 자체 또는 음영 처리 된 뷰의 즉각적인 수퍼 뷰의 layoutSubviews
메서드에서 shadowPath
을 업데이트해야한다는 것입니다.내 데모 비디오에서는 을 layoutSubviews
녹색 상자보기 또는 녹색 상자의 즉각적인 수퍼 뷰 방법으로 업데이트해야한다는 것을 의미합니다.
나는 그의 유일한 직업 그릴과 파단 중 하나의 그림자 애니메이션을하는 것입니다
ShadowingView
클래스를 작성하기로 결정했습니다.
@interface ShadowingView : UIView
@property (nonatomic, strong) IBOutlet UIView *shadowedView;
@end
가 내 스토리 보드에서 내 휴대보기에 추가, ShadowingView
을 사용하려면 다음은 인터페이스입니다. 사실 그것은 셀 내부의 스택보기 안에 중첩되어 있습니다. 그런 다음 녹색 상자를 ShadowingView
의 하위보기로 추가하고 콘센트를 녹색 상자에 shadowedView
연결했습니다.
ShadowingView
구현은 세 부분으로 구성됩니다.
경우와 같이이 방법 (애니메이션 블록 내에서 실행된다
@implementation ShadowingView
- (void)layoutSubviews {
[super layoutSubviews];
CALayer *layer = self.layer;
layer.backgroundColor = nil;
CALayer *shadowedLayer = self.shadowedView.layer;
if (shadowedLayer == nil) {
layer.shadowColor = nil;
return;
}
NSAssert(shadowedLayer.superlayer == layer, @"shadowedView must be my direct subview");
layer.shadowColor = UIColor.blackColor.CGColor;
layer.shadowOffset = CGSizeMake(0, 1);
layer.shadowOpacity = 0.5;
layer.shadowRadius = 3;
layer.masksToBounds = NO;
CGFloat radius = shadowedLayer.cornerRadius;
layer.shadowPath = CGPathCreateWithRoundedRect(shadowedLayer.frame, radius, radius, nil);
}
테이블 : 하나는 자신의 층 상에 층 그림자 속성 설정의 layoutSubviews
있어서, 그 shadowedView
하위 뷰 주위 그림자를 그리는 것이다 보기) 셀의 크기의 변화를 애니메이션 및 방법은 "액션이"shadowPath
를 업데이트 한 후 실행하는 shadowPath
는, 코어 애니메이션 보이는 설정합니다. 보이는 방법 중 하나는 actionForLayer:forKey:
을 레이어의 위임에 보내고 위임은 ShadowingView
입니다. 가능한 경우 적절한 조치를 취하기 위해 actionForLayer:forKey:
을 무시합니다. 할 수 없다면 super
으로 전화하면됩니다.
코어 애니메이션은 실제로 shadowPath
의 값을 변경 전에 shadowPath
세터 내부에서 작업을 요청한다는 것을 이해하는 것이 중요하다.
조치를 제공하기 위해 우리는 키가 @"shadowPath"
이고, 기존 값이 shadowPath
이고, 레이어에 이미 bounds.size
인 애니메이션이 있는지 확인합니다. 기존 bounds.size
애니메이션을 찾는 이유는 무엇입니까? 기존 애니메이션에는 지속 시간과 타이밍 기능이 있기 때문에 shadowPath
에 애니메이션을 사용해야합니다. 모든 순서에 있다면, 우리는, 애니메이션의 복사본을 만드는 작업에 저장하고 작업 복귀, shadowPath
기존 잡아 :
- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event {
if (![event isEqualToString:@"shadowPath"]) { return [super actionForLayer:layer forKey:event]; }
CGPathRef priorPath = layer.shadowPath;
if (priorPath == NULL) { return [super actionForLayer:layer forKey:event]; }
CAAnimation *sizeAnimation = [layer animationForKey:@"bounds.size"];
if (![sizeAnimation isKindOfClass:[CABasicAnimation class]]) { return [super actionForLayer:layer forKey:event]; }
CABasicAnimation *animation = [sizeAnimation copy];
animation.keyPath = @"shadowPath";
ShadowingViewAction *action = [[ShadowingViewAction alloc] init];
action.priorPath = priorPath;
action.pendingAnimation = animation;
return action;
}
@end
무엇처럼 액션 모양을합니까? 인터페이스는 다음과 같습니다.
@interface ShadowingViewAction : NSObject <CAAction>
@property (nonatomic, strong) CABasicAnimation *pendingAnimation;
@property (nonatomic) CGPathRef priorPath;
@end
구현에는 runActionForKey:object:arguments:
메소드가 필요합니다. 이 방법에서는, 우리는 우리가 구원을 멀리 오래된 shadowPath
새로운 shadowPath
를 사용하여 actionForLayer:forKey:
에서 만든 애니메이션을 업데이트 한 다음 우리는 레이어에 애니메이션을 추가 할 수 있습니다. ARC는 CGPath
개체를 관리하지 않기 때문에
우리는 또한, 저장된 경로의 유지 수를 관리해야합니다.
@implementation ShadowingViewAction
- (void)runActionForKey:(NSString *)event object:(id)anObject arguments:(NSDictionary *)dict {
if (![anObject isKindOfClass:[CALayer class]] || _pendingAnimation == nil) { return; }
CALayer *layer = anObject;
_pendingAnimation.fromValue = (__bridge id)_priorPath;
_pendingAnimation.toValue = (__bridge id)layer.shadowPath;
[layer addAnimation:_pendingAnimation forKey:@"shadowPath"];
}
- (void)setPriorPath:(CGPathRef)priorPath {
CGPathRetain(priorPath);
CGPathRelease(_priorPath);
_priorPath = priorPath;
}
- (void)dealloc {
CGPathRelease(_priorPath);
}
@end
그림자가 하나의 셀 주위에 있거나 전체 테이블 주위에 있어야합니까? –