3.Popping笔记--Circle View

Popping笔记。Github上搜索"Popping"即可下载源代码。

Circle View


分析动画。

这个动画很简单,一个圆圈,一个slider,滑动slider圆圈会变,并且有spring的效果。


CircleView.m

-(id)initWithFrame:(CGRect)frame方法中首先进行断言:一个圆的高和宽一定是相同的。接着添加circleLayer,来到addCircleLayer方法。

- (void)addCircleLayer
{
    CGFloat lineWidth = 4.f;
    CGFloat radius = CGRectGetWidth(self.bounds)/2 - lineWidth/2;
    self.circleLayer = [CAShapeLayer layer];
    CGRect rect = CGRectMake(lineWidth/2, lineWidth/2, radius * 2, radius * 2);
    self.circleLayer.path = [UIBezierPath bezierPathWithRoundedRect:rect
                                                  cornerRadius:radius].CGPath;

    self.circleLayer.strokeColor = self.tintColor.CGColor;
    self.circleLayer.fillColor = nil;
    self.circleLayer.lineWidth = lineWidth;
    self.circleLayer.lineCap = kCALineCapRound;
    self.circleLayer.lineJoin = kCALineJoinRound;
    
    [self.layer addSublayer:self.circleLayer];
}

我们首先得到一个CAShapeLayer,通过设置其path属性来画一个圆。

path属性是通过UIBezierPath来设置的,注意其类型是CGPathRef

接着设置shape layer的strokeColor, lineWidth等属性来画出我们想要的圆。

接着到CircleViewController.m文件中。

首先添加circleView,即我们刚才分析的对象。设置其宽度高度都为200,中点为屏幕的中点。

此时运行程序,应该会有一个完整的圆环。

接下来我们需要添加一个slider。

- (void)addSlider
{
    UISlider *slider = [UISlider new];
    slider.value = 0.7f;
    slider.tintColor = [UIColor customBlueColor];
    slider.translatesAutoresizingMaskIntoConstraints = NO;
    [slider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
    [self.view addSubview:slider];
    NSDictionary *views = NSDictionaryOfVariableBindings(slider, _circleView);

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_circleView]-(40)-[slider]"
                                                                      options:0
                                                                      metrics:nil
                                                                        views:views]];

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[slider]-|"
                                                                      options:0
                                                                      metrics:nil
                                                                        views:views]];
    [self.circleView setStrokeEnd:slider.value animated:NO];
}

创建一个slider,设置其初始值为0.7f(这就是为什么刚上来圆环并不完整),注意这里并没有在刚开始创建slider的时候设置其frame,center之类的属性,而是通过addConstraints:方法来限定slider的位置。

首先需要设置slider.translatesAutoresizingMaskIntoConstraints = NO,意思是说我们不使用autoresizingMask而是通过addConstraints。

NSDictionary *views = NSDictionaryOfVariableBindings(slider, _circleView);

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_circleView]-(40)-[slider]"
                                                                  options:0
                                                                  metrics:nil
                                                                    views:views]];

[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[slider]-|"
                                                                  options:0
                                                                  metrics:nil
                                                                    views:views]];

看代码可以知道我们加了两个constraints:一个是水平方向的(H),一个是竖直方向的(V)

在竖直方向上,我们竖直排列circleView和slider,其间距为40。
在水平方向上,我们将slider放在一行上,两边距离边界的长度默认(处于蓝色虚线?)

而NSDictionaryOfVariableBingdings()的作用在于,说明@"V:[_circleView]-(40)-[slider]"和@"H:|-[slider]-|"中,_circleView和slider所代表的对象是哪个。相当于:

@"_circleView":_circleView (或者self.circleView)

@"slider":slider


现在运行程序,发现圆环已经不完整(0.7),现在我们需要监听slider:改变slider的值,圆环也会跟着改变。

在addSlider方法中,

[slider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];

接着sliderChanged:方法:

[self.circleView setStrokeEnd:slider.value animated:YES];

回到CircleView.m中,找到setStrokeEnd:animated:方法。

- (void)setStrokeEnd:(CGFloat)strokeEnd animated:(BOOL)animated
{
    if (animated) {
        [self animateToStrokeEnd:strokeEnd];
        return;
    }
    self.circleLayer.strokeEnd = strokeEnd;
}

可以看到,如果animated的话,则设置spring动画,并返回;如果!animated的话,则直接设置shape layer的strokeEnd的值。这也就对应了两种不同的情况:应用刚进入的时候直接设置strokeEnd的值使圆环处于0.7处;拖动slider,每次变化的时候将根据当前的value变化圆环。

- (void)animateToStrokeEnd:(CGFloat)strokeEnd
{
    POPSpringAnimation *strokeAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPShapeLayerStrokeEnd];
    strokeAnimation.toValue = @(strokeEnd);
    strokeAnimation.springBounciness = 12.f;
    strokeAnimation.removedOnCompletion = NO;
    [self.circleLayer pop_addAnimation:strokeAnimation forKey:@"layerStrokeAnimation"];
}

这个方法很简单,给shape layer的strokeEnd属性加上动画效果。(strokeEnd可以理解为所占的比例?)

将strokeAnimation.removedOnCompletion = NO;这一行注释似乎也不影响运行结果,不知这一行的目的?


结束。

你可能感兴趣的:(3.Popping笔记--Circle View)