1

CoreAnimation でシェイプをアニメーション化するのと同様の問題に直面しています

私には習慣がありますUIView

MyUIView

- (void)drawRect:(CGRect)rect {
    // Right here, I might also draw some triangle, circle which I do not wish
    // to be animated.

    // ...
    // Calculate minX, minY, ... based on rect and self->value.
    // ...

    // Draw a rounded rectangle based on minX, minY, ...
    // The x-location of rounded rectangle will be different for difference self->value
    CGContextMoveToPoint(context, minx, midy);
    CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
    ...
    ...
    CGContextDrawPath(context, kCGPathFillStroke);        
}

// Usually trigger by controller via button clicked
- (void) setValueViaButtonClicked:(double) value {
    self->currentValue = value;
    dispatch_async(dispatch_get_main_queue(), ^{
        [self setNeedsDisplay];
    });
}

現在、古い値とは異なる新しい値でボタンをクリックするたびに、角丸四角形が古い位置から新しい位置に移動するのを確認できますが、アニメーションは表示されません。

明示的なボタンクリック時のみ、アニメーションを作成したいと思います。私が見たほとんどの例では、アニメーション コードはコントローラー内で実行されます。

  • アニメーションは Layer と CGPathCreateMutable を介して行われます
  • Layer と CGPathCreateMutable の作成は、View Controller で実行されます。

MyUIViewを介して上記のタスクを実行するにはどうすればよいsetValueViaButtonClickedでしょうか? drawRect からの適切なrect情報がないため、から作成されたパスの情報をどのように構成するのCGPathCreateMutableでしょうか?

4

1 に答える 1

0

使用しないと思いますがCoreAnimationCoreGraphics現在の状態/値を描画するだけです。静止画像の代わりにアニメーションになると、CoreAnimationレイヤーに切り替えます。あなたの場合、UIViewサブクラスを作成CAShapeLayerし、三角形(または任意の形状)に を追加します。

次のようになります。

@interface MyView ()
@property (nonatomic, strong) CAShapeLayer *shapeLayer;
@property (nonatomic, assign) double currentValue;
@end

@implementation MyView

-(instancetype)init {
  if (self = [super init]) {
    [self setup];
  }
  return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
  if (self = [super initWithCoder:aDecoder]) {
    [self setup];
  }
  return self;
}

- (instancetype)initWithFrame:(CGRect)frame
{
  self = [super initWithFrame:frame];
  if (self) {
    [self setup];
  }
  return self;
}

- (void)setup {
  CAShapeLayer *shape = [CAShapeLayer layer];
  shape.contentsScale = [[UIScreen mainScreen] scale];
  self.shapeLayer = shape;
  [self.layer addSublayer:shape];
}

- (void)layoutSubviews {
  [super layoutSubviews];
  self.shapeLayer.frame = self.bounds;
  self.shapeLayer.path = [self bezierPathForValue:self.currentValue].CGPath;
}

- (UIBezierPath *)bezierPathForValue:(double)value {
  UIBezierPath *path = [UIBezierPath bezierPath];
  [path moveToPoint:...]; // points are depending on currentValue
  return path;
}

- (void)setValueViaButtonClicked:(double) value {
  double oldValue = self.currentValue;
  self.currentValue = value;

  // update model value
  self.shapeLayer.path = [self bezierPathForValue:value].CGPath;

  CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
  pathAnimation.fromValue = (id)[self bezierPathForValue:oldValue].CGPath;
  pathAnimation.toValue = (id)[self bezierPathForValue:value].CGPath;
  pathAnimation.duration = 0.3f;
  [self.shapeLayer addAnimation:pathAnimation forKey:nil];
}

@end
于 2016-04-02T17:06:50.880 に答える