在Long Press事件上画一个圆圈

时间:2015-03-31 07:59:03

标签: ios uigesturerecognizer nstimer cabasicanimation cashapelayer

当用户点击按钮时,我在屏幕上画了一个圆圈。已设置动画持续时间,并且还设置了from和to值。

我想要实现的是,动画应以某种方式开始,因为用户长按按钮并继续直到他在屏幕上保持敲击,即长按的持续时间。 一旦用户抬起他的手指,圆圈应该停止到它到目前为止完成的位置。

这是我的代码:

-(void)startCircularAnimation{

int radius = 50;
CAShapeLayer *circle = [CAShapeLayer layer];
// Make a circular shape
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius)
                                         cornerRadius:radius].CGPath;
// Center the shape in self.view
circle.position = CGPointMake(CGRectGetMidX(self.view.frame)-radius,
                              CGRectGetMidY(self.view.frame)-radius);

// Configure the apperence of the circle
circle.fillColor = [UIColor clearColor].CGColor;
circle.strokeColor = [UIColor redColor].CGColor;
circle.lineWidth = 5;

// Add to parent layer
[self.view.layer addSublayer:circle];

// Configure animation
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
drawAnimation.duration            = 15.0;
drawAnimation.repeatCount         = 1.0;  // Animate only once..

// Animate from no part of the stroke being drawn to the entire stroke being drawn
drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
drawAnimation.toValue   = [NSNumber numberWithFloat:counter/drawAnimation.duration];

// Experiment with timing to get the appearence to look the way you want
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

// Add the animation to the circle
[circle addAnimation:drawAnimation forKey:@"draw"];
}

此方法执行动画,并且从我在触摸开始时使用长按处理程序方法启动的计时器计算from值。我无法在长时间内获得完美的持续时间。

长按事件方法是这样的。

 - (void)_handleLongPressGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer{

    switch (gestureRecognizer.state) {
    case UIGestureRecognizerStateBegan:
    {
        counter = 0;
        timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(incrementCounter) userInfo:nil repeats:YES];


    }
    case UIGestureRecognizerStateEnded:{
        NSLog(@"State ended");
         [timer invalidate];

        break;
    }
    case UIGestureRecognizerStateCancelled:{
        NSLog(@"State cancelled");
        break;
    }
    case UIGestureRecognizerStateFailed:
    {

        break;
    }
    default:
        break;
  }

}

和增量计数器方法如下

- (void)incrementCounter {
 counter++;
[self startCircularAnimation];
}

在用户将手指放在屏幕上之前,这并没有给我带来所需的画圆效果。

请在代码中提出建议,以获得所需的功能。

提前致谢。

2 个答案:

答案 0 :(得分:3)

您想要遵循苹果指南https://developer.apple.com/library/ios/qa/qa1673/_index.html

因此,在您的界面中,我要声明以下内容

@interface ViewController ()

@property (nonatomic, strong) CAShapeLayer *circle;
@property (nonatomic, strong) CABasicAnimation *drawAnimation;
@property (strong, nonatomic) IBOutlet UIButton *circleButton;


@end

然后在视图中加载

- (void)viewDidLoad
{
    [super viewDidLoad];

    int radius = 50;
    self.circle = [CAShapeLayer layer];
    // Make a circular shape
    self.circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius)
                                          cornerRadius:radius].CGPath;
    // Center the shape in self.view
    self.circle.position = CGPointMake(CGRectGetMidX(self.view.frame)-radius,
                               CGRectGetMidY(self.view.frame)-radius);

    // Configure the apperence of the circle
    self.circle.fillColor = [UIColor clearColor].CGColor;
    self.circle.strokeColor = [UIColor redColor].CGColor;
    self.circle.lineWidth = 5;

    self.circle.strokeEnd = 0.0f;

    // Add to parent layer
    [self.view.layer addSublayer:_circle];

    // Target for touch down (hold down)
    [self.circleButton addTarget:self action:@selector(startCircleAnimation) forControlEvents:UIControlEventTouchDown];

    // Target for release
    [self.circleButton addTarget:self action:@selector(endCircleAnimation) forControlEvents:UIControlEventTouchUpInside];

    /**
     Don't start Animation in viewDidLoad to achive the desired effect
    */


}

启动动画并恢复动画的功能(可能需要更好的名字)

-(void)startCircleAnimation{
    if (_drawAnimation) {
        [self resumeLayer:_circle];
    } else {
        [self circleAnimation];
    }
}

结束动画的功能

-(void)endCircleAnimation{
    [self pauseLayer:_circle];
}

生成动画的功能

- (void)circleAnimation
{
     // Configure animation
     self.drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
     self.drawAnimation.duration            = 10.0;
     self.drawAnimation.repeatCount         = 1.0; // Animate only once..


     // Animate from no part of the stroke being drawn to the entire stroke being drawn
     self.drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];

     // Set your to value to one to complete animation
     self.drawAnimation.toValue   = [NSNumber numberWithFloat:1.0f];

     // Experiment with timing to get the appearence to look the way you want 
     self.drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

     // Add the animation to the circle
     [self.circle addAnimation:_drawAnimation forKey:@"draw"];
}

从苹果暂停和停止功能

   - (void)pauseLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
    layer.speed = 0.0;
    layer.timeOffset = pausedTime;
}

  - (void)resumeLayer:(CALayer*)layer
  {
      CFTimeInterval pausedTime = [layer timeOffset];
      layer.speed = 1.0;
      layer.timeOffset = 0.0;
      layer.beginTime = 0.0;
      CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
      layer.beginTime = timeSincePause;
  }

您想要从中获取的要点是,您没有记录按钮被按下的时间,以便仅记录从按钮UIControlEventTouchDown和UIControlEventTouchUpInside发送的事件

编辑为GIF

Animation


答案 1 :(得分:0)

我认为你应该从与计数器价值相关的价值中获得你的价值,这将使得绘画从上次用户抬起手指时所留下的内容开始。

你还应该让你的计时器的时间间隔更小,1秒太长,0.1秒会更好。