【问题标题】:Perform animation within custom UIView only仅在自定义 UIView 中执行动画
【发布时间】:2013-03-11 10:06:25
【问题描述】:

我面临与Animating a shape with 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 的创建在视图控制器中执行。

我想知道,我怎么可能通过MyUIViewsetValueViaButtonClicked 执行上述任务?由于没有来自drawRect的正确rect信息,我将如何配置从CGPathCreateMutable创建的路径的信息?

【问题讨论】:

    标签: iphone ios


    【解决方案1】:

    我认为您不使用 CoreAnimation 而是使用 CoreGraphics 来绘制当前状态/值。每当涉及到动画而不是静态图像时,我都会切换到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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多