仿半糖下拉刷新 -- PDPullToRefresh

周末仿寫(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ā)。


Blog地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,828評(píng)論 4 61
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,366評(píng)論 25 708
  • 目標(biāo) 決定自己的優(yōu)先級(jí)并于其上集中 對(duì)付時(shí)間浪費(fèi)的策略 建立時(shí)間管理計(jì)劃 成為更好的時(shí)間管理者 Quotation...
    青衫磊落_H閱讀 356評(píng)論 0 0
  • 時(shí)間 真的是這個(gè)世界上最好的跨度 讓?xiě)K痛變得蒼白 讓執(zhí)著的人選擇離開(kāi) 然后歷經(jīng)滄桑人來(lái)人往 你會(huì)明白 萬(wàn)般皆是命 ...
    大佐先森閱讀 579評(píng)論 0 1
  • 1、WOW前60級(jí)MOD的內(nèi)容 說(shuō)白了就是有些高級(jí)玩家對(duì)MMORPG網(wǎng)游WOW不滿(mǎn),覺(jué)得暴雪做的任務(wù)與劇情不符合自...
    westwind1985閱讀 813評(píng)論 0 0

友情鏈接更多精彩內(nèi)容