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;這一行注釋似乎也不影響運行結果,不知這一行的目的?


結束。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現這些動畫的過程并不復雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,551評論 6 30
  • 轉載:http://www.lxweimin.com/p/32fcadd12108 每個UIView有一個伙伴稱為l...
    F麥子閱讀 6,288評論 0 13
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現這些動畫的過程并不復雜,今天將帶大家一窺iOS動畫全貌。在這里你可以看...
    F麥子閱讀 5,141評論 5 13
  • *7月8日上午 N:Block :跟一個函數塊差不多,會對里面所有的內容的引用計數+1,想要解決就用__block...
    炙冰閱讀 2,515評論 1 14
  • 1.1.1斥責只能求得一時的效果,無法從根本上解決問題,應該以對等視線進行良性溝通,不能因為一時的喝止產生效果而棄...
    楊秀兵閱讀 257評論 0 0