周末仿寫(xiě)了半糖的下拉刷新,學(xué)了兩句法語(yǔ)
- C'est La Vie
- La Vie est belle
C'est La Vie 通常是用在較為消極的事情發(fā)生時(shí),用于自我安慰或自我解嘲,鼓勵(lì)自己或他人即使遇到了再大的難處,也要坦然笑對(duì)生活。哈哈,雞湯一下開(kāi)始正文。

示例
-
半糖
半糖 -
PDPullToRefresh
PDPullToRefresh
思路
PDPullToRefresh是給UIScrollView加的分類(lèi),包括PDHeaderRefreshView和PDFooterRefreshView ,整個(gè)刷新過(guò)程可分為兩部分
- 下拉時(shí) - C'est La Vie 動(dòng)畫(huà)
- 刷新時(shí) - La Vie est belle 動(dòng)畫(huà)
C'est La Vie 動(dòng)畫(huà)
首先得拿到C'est La Vie的字形,這里用到了CoreText,拿到字形后添加到layer.path上顯示
CGMutablePathRef letters = CGPathCreateMutable();
CTFontRef font = CTFontCreateWithName(CFSTR("HelveticaNeue-UltraLight"), pFontSize, NULL);
NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:
(__bridge id)font, kCTFontAttributeName,
nil];
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:animationString
attributes:attrs];
CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)attrString);
CFArrayRef runArray = CTLineGetGlyphRuns(line);
// for each RUN
for (CFIndex runIndex = 0; runIndex < CFArrayGetCount(runArray); runIndex++)
{
// Get FONT for this run
CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runArray, runIndex);
CTFontRef runFont = CFDictionaryGetValue(CTRunGetAttributes(run), kCTFontAttributeName);
// for each GLYPH in run
for (CFIndex runGlyphIndex = 0; runGlyphIndex < CTRunGetGlyphCount(run); runGlyphIndex++)
{
// get Glyph & Glyph-data
CFRange thisGlyphRange = CFRangeMake(runGlyphIndex, 1);
CGGlyph glyph;
CGPoint position;
CTRunGetGlyphs(run, thisGlyphRange, &glyph);
CTRunGetPositions(run, thisGlyphRange, &position);
// Get PATH of outline
{
CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyph, NULL);
CGAffineTransform t = CGAffineTransformMakeTranslation(position.x, position.y);
CGPathAddPath(letters, &t, letter);
CGPathRelease(letter);
}
}
}
CFRelease(line);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointZero];
[path appendPath:[UIBezierPath bezierPathWithCGPath:letters]];
CGPathRelease(letters);
CFRelease(font);
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.frame = self.animationLayer.bounds;
pathLayer.bounds = CGPathGetBoundingBox(path.CGPath);
pathLayer.geometryFlipped = YES;
pathLayer.path = path.CGPath;
pathLayer.strokeColor = [UIColor colorWithRed:234.0/255 green:84.0/255 blue:87.0/255 alpha:1].CGColor;
pathLayer.fillColor = nil;
pathLayer.lineWidth = 1.0f;
pathLayer.lineJoin = kCALineJoinBevel;
然后用KVO監(jiān)聽(tīng)ScrollView的contentOffset屬性,與pathLayer的strokeEnd關(guān)聯(lián)起來(lái),C'est La Vie就可以隨著下拉做動(dòng)畫(huà)啦。
La Vie est belle 動(dòng)畫(huà)
La Vie est belle與C'est La Vie的動(dòng)畫(huà)不同,它是一直閃動(dòng)著的,還是先拿到La Vie est belle的字形,這里用CAGradientLayer可以方便的處理顏色漸變。
CAGradientLayer *gradientLayer = (CAGradientLayer *)self.gradientLayer;
if([gradientLayer animationForKey:kAnimationKey] == nil)
{
// 通過(guò)不斷改變漸變的起止范圍,來(lái)實(shí)現(xiàn)光暈效果
CABasicAnimation *startPointAnimation = [CABasicAnimation animationWithKeyPath:gradientStartPointKey];
startPointAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(1.0, 0)];
startPointAnimation.timingFunction = [CAMediaTimingFunction functionWithName:_animationPacing];
CABasicAnimation *endPointAnimation = [CABasicAnimation animationWithKeyPath:gradientEndPointKey];
endPointAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(1 + pHaloWidth, 0)];
endPointAnimation.timingFunction = [CAMediaTimingFunction functionWithName:_animationPacing];
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = @[startPointAnimation, endPointAnimation];
group.duration = pHaloDuration;
group.timingFunction = [CAMediaTimingFunction functionWithName:_animationPacing];
group.repeatCount = HUGE_VALF;
[gradientLayer addAnimation:group forKey:kAnimationKey];
}
使用
安裝
- 添加
pod 'PDPullToRefresh'到你的 Podfile ,然后pod install。 - 手動(dòng)添加到你的Xcode項(xiàng)目中,
#import "PDPullToRefresh.h"。
添加下拉刷新
[tableView pd_addHeaderRefreshWithNavigationBar:YES andActionHandler:^{
// prepend data to dataSource, insert cells at top of table view
// call [tableView.pdHeaderRefreshView stopRefreshing] when done
}];
添加上拉刷新
[tableView pd_addFooterRefreshWithNavigationBar:YES andActionHandler:^{
// prepend data to dataSource, insert cells at top of table view
// call [tableView.pdFooterRefreshView stopRefreshing] when done
}];
立即刷新
[tableView.pdHeaderRefreshView startRefreshing];
自定義
目前僅支持下拉距離自定義,默認(rèn)高度為80
@property (nonatomic, assign) CGFloat pdHeaderRefreshViewHeight;
@property (nonatomic, assign) CGFloat pdFooterRefreshViewHeight;
最后
附上Github地址,外加感謝半塘、SVPullToRefresh對(duì)我的啟發(fā)。

