Iphone 仅在自定义UIView中执行动画

Iphone 仅在自定义UIView中执行动画,iphone,ios,Iphone,Ios,我面临着和你一样的问题 我有一个自定义的ui视图 MyUIView 当前,每当我单击具有不同于旧值的新值的按钮时,我都可以看到圆角矩形从旧位置移动到新位置,但没有动画。 我想有动画,只有在显式按钮点击。对于我所看到的大多数示例,动画代码是在控制器中通过 动画通过层和CGPathCreateMutable完成 层和CGPathCreateMutable的创建在视图控制器中执行 我想知道,我如何能够通过单击的MyUIView的setvaluevia按钮执行上述任务?由于drawRect中没有正确

我面临着和你一样的问题

我有一个自定义的
ui视图

MyUIView 当前,每当我单击具有不同于旧值的新值的按钮时,我都可以看到圆角矩形从旧位置移动到新位置,但没有动画。

我想有动画,只有在显式按钮点击。对于我所看到的大多数示例,动画代码是在控制器中通过

  • 动画通过层和CGPathCreateMutable完成
  • 层和CGPathCreateMutable的创建在视图控制器中执行

我想知道,我如何能够通过单击的
MyUIView
setvaluevia按钮执行上述任务?由于drawRect中没有正确的
rect
信息,我如何为从
CGPathCreateMutable
创建的路径配置信息?

我认为您不使用
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
@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