3.Popping笔记--Circle View

作者: ForeverYoung21 | 来源:发表于2015-05-22 21:28 被阅读142次

    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

      本文链接:https://www.haomeiwen.com/subject/fxzlqttx.html