だから私はあなたがこのような何かを持っていると思います:
(私はシミュレータで「デバッグ>スローアニメーション」オン。)そして、あなたは影がそのにジャンプ道を好きではありません新しいサイズ。あなたはこの代わりにしたい:
あなたは私のテストプロジェクトin this github repositoryを見つけることができます。
アニメーションパラメータを取得し、テーブルビューのアニメーションブロックにアニメーションを追加するのは難しいことではありませんが、不可能ではありません。最も難しいのは、影付きのビュー自体のlayoutSubviews
メソッドまたは影付きのビューの即時スーパービューのメソッドshadowPath
を更新する必要があることです。私のデモビデオでは、は、緑色のボックスビューまたは緑色ボックスの即時のスーパービューのlayoutSubviews
メソッドで更新する必要があることを示しています。
ShadowingView
クラスを作成して、そのサブビューの1つの影を描き、アニメーション化することを唯一の仕事としました。ここでは、インターフェイスがあります:
@interface ShadowingView : UIView
@property (nonatomic, strong) IBOutlet UIView *shadowedView;
@end
ShadowingView
を使用するには、私は私のストーリーボードの私の細胞ビューにこれを追加しました。実際には、セル内のスタックビュー内にネストされています。次に、緑のボックスをShadowingView
のサブビューとして追加し、緑のボックスにshadowedView
のコンセントを接続しました。
ShadowingView
実装には3つの部分があります。
場合のように、この方法は、(アニメーションブロック内で実行される
@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
の更新後に実行するアクションを探します。それが見える方法の1つは、actionForLayer:forKey:
をレイヤのデリゲートに送信し、デリゲートはShadowingView
です。可能であれば適切な処置を行うため、actionForLayer:forKey:
を上書きします。できない場合は、super
に電話するだけです。
Core Animationのが実際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:
メソッドが必要です。この方法では、actionForLayer:forKey:
で作成したアニメーションを、保存済みの古いshadowPath
と新しいshadowPath
を使用して更新し、アニメーションをレイヤーに追加します。
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
シャドウは1つのセルの周りまたはテーブル全体の周りにあると想定されていますか? –