iOS-OC仿Boss直聘下拉刷新動畫

??在刷即刻的時候徙瓶,突然發(fā)現(xiàn)它的首頁刷新動畫還不錯,因此我就仿寫了下boss直聘App的下拉刷新動畫(別問為啥)嫉称,在這里記錄下來供大家參考討論侦镇。最終運(yùn)行效果如下:
QQ20180620-162220-HD.gif

??廢話不多說開始上代碼了。首先創(chuàng)建一個CYXRefreshHeader

@interface CYXRefreshHeader : UIView
/*刷新block*/
@property (nonatomic,strong) void(^refresh)(void);
/*開始刷新*/
-(void)startRefresh;
/*結(jié)束刷新*/
-(void)endRefresh;
@end

初始化三個點(diǎn)的Layer

-(instancetype)init{
    if (self = [super init]) {
        self.backgroundColor = [UIColor whiteColor];
        self.frame = CGRectMake(0, HeaderHeight, HeaderWidth, HeaderHeight);
        [self.layer addSublayer:self.firstPointLayer];
        [self.layer addSublayer:self.secondPointLayer];
        [self.layer addSublayer:self.thirdPointLayer];
        self.firstPointLayer.frame = CGRectMake(HeaderWidth/2-RefreshArcRadius, HeaderHeight/2-RefreshArcRadius, RefreshArcRadius*2, RefreshArcRadius*2);
        self.secondPointLayer.frame = CGRectMake(HeaderWidth/2-RefreshArcRadius, HeaderHeight/2-RefreshArcRadius, RefreshArcRadius*2, RefreshArcRadius*2);
        self.thirdPointLayer.frame = CGRectMake(HeaderWidth/2-RefreshArcRadius, HeaderHeight/2-RefreshArcRadius, RefreshArcRadius*2, RefreshArcRadius*2);
        self.firstPointLayer.path = [self pointPath].CGPath;
        self.secondPointLayer.path = [self pointPath].CGPath;
        self.thirdPointLayer.path = [self pointPath].CGPath;
    }
    return self;
}
#pragma mark ---Path
-(UIBezierPath *)pointPath{
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(RefreshArcRadius, RefreshArcRadius) radius:RefreshArcRadius startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    return path;
}

在父視圖改變的時候設(shè)置監(jiān)聽scrollview的滑動偏移量

/*父視圖改變的時候*/
- (void)willMoveToSuperview:(UIView *)newSuperview {
    [super willMoveToSuperview:newSuperview];
    if ([newSuperview isKindOfClass:[UIScrollView class]]) {
        self.scrollView = (UIScrollView *)newSuperview;
        self.centerX = self.scrollView.width/2;
        self.bottom = 0;
        [self.scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
    }else {
        [self.superview removeObserver:self forKeyPath:@"contentOffset"];
    }
}

??這里- (void)willMoveToSuperview:(UIView *)newSuperview 方法的調(diào)用時機(jī):
??當(dāng)自己重寫一個UIView的時候有可能用到這個方法,當(dāng)本視圖的父類視圖改變的時候,系統(tǒng)會自動的執(zhí)行這個方法.newSuperview是本視圖的新父類視圖.newSuperview有可能是nil.
??在監(jiān)聽偏移量的方法里實(shí)現(xiàn)隨著偏移量三個點(diǎn)的變化:

#pragma mark ---Kvo
/*監(jiān)聽偏移量*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"contentOffset"]) {
        self.offSet =  self.scrollView.contentOffset.y;
        [self setOffSetUI];
    }
}
/*設(shè)置*/
-(void)setOffSetUI{
    //如果到達(dá)臨界點(diǎn)织阅,則執(zhí)行刷新動畫
    if (!self.isAnimating&&self.offSet<=0) {
        CGFloat scale = -self.offSet/RefreshFullOffset;
        if (scale>1) {scale=1;}
        if (scale<0) {scale=0;}
        CGFloat centerX = HeaderWidth/2;
        CGFloat maxLeftX = centerX-RefreshMaxWidth;
        CGFloat maxLeftDistance = centerX - maxLeftX;
        CGFloat maxRightX = centerX+RefreshMaxWidth;
        CGFloat maxRightDistance = maxRightX - centerX;
        
        self.firstPointLayer.frame = CGRectMake(centerX-maxLeftDistance*scale-RefreshArcRadius, HeaderHeight/2-RefreshArcRadius, RefreshArcRadius*2, RefreshArcRadius*2);
        self.thirdPointLayer.frame = CGRectMake(centerX+maxRightDistance*scale-RefreshArcRadius, HeaderHeight/2-RefreshArcRadius, RefreshArcRadius*2, RefreshArcRadius*2);
        CGFloat topY =-(RefreshFullOffset/2-RefreshFullOffset/2.0*(1.0-scale))-RefreshArcRadius*2;//y坐標(biāo)的變化
        self.top = topY;
    }
    if (-self.offSet >= RefreshFullOffset && !self.isAnimating && !self.scrollView.dragging) {
        //刷新
        [self startAnimation];
        if (self.refresh) {
            self.refresh();
        }
    }
}

再達(dá)到臨界值的時候執(zhí)行刷新動作并執(zhí)行刷新動畫:

/*執(zhí)行動畫*/
-(void)startAnimation{
    self.isAnimating = YES;
    [UIView animateWithDuration:0.5 animations:^{
        UIEdgeInsets inset = self.scrollView.contentInset;
        inset.top = RefreshFullOffset;
        self.scrollView.contentInset = inset;
    }];
    CAKeyframeAnimation * animation = [self opacityAnimation];
    [self.firstPointLayer addAnimation:animation forKey:@"opacity"];
    
    animation = [self opacityAnimation];
    animation.beginTime = CACurrentMediaTime()+KeyAnimationDuration/2;
    [self.secondPointLayer addAnimation:animation forKey:@"opacity"];
    
    animation = [self opacityAnimation];
    animation.beginTime = CACurrentMediaTime()+KeyAnimationDuration;
    [self.thirdPointLayer addAnimation:animation forKey:@"opacity"];
}
-(CAKeyframeAnimation *)opacityAnimation{
    CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
    animation.duration = KeyAnimationDuration;
    
    animation.repeatCount = HUGE_VALF;
    animation.fillMode = kCAFillModeForwards;
    animation.duration = KeyAnimationDuration*2;
    animation.values = @[[NSNumber numberWithFloat:1.0f],
                         [NSNumber numberWithFloat:0.0f],
                         [NSNumber numberWithFloat:1.0f],
                         [NSNumber numberWithFloat:1.0f]];
    return animation;
}

最后再實(shí)現(xiàn)結(jié)束刷新的方法即可:

 -(void)endRefresh{
   [UIView animateWithDuration:0.5 animations:^{
        UIEdgeInsets inset = self.scrollView.contentInset;
        inset.top = 0.f;
        self.scrollView.contentInset = inset;
   } completion:^(BOOL finished) {
        [self stopAnimation];
        [self initLayerFrame];
   }];
}

/*初始化layer坐標(biāo)*/
-(void)initLayerFrame{
    self.firstPointLayer.frame = CGRectMake(HeaderWidth/2-RefreshArcRadius, HeaderHeight/2-RefreshArcRadius, RefreshArcRadius*2, RefreshArcRadius*2);
    self.secondPointLayer.frame = CGRectMake(HeaderWidth/2-RefreshArcRadius, HeaderHeight/2-RefreshArcRadius, RefreshArcRadius*2, RefreshArcRadius*2);
    self.thirdPointLayer.frame = CGRectMake(HeaderWidth/2-RefreshArcRadius, HeaderHeight/2-RefreshArcRadius, RefreshArcRadius*2, RefreshArcRadius*2);
}
/*停止動畫*/
-(void)stopAnimation{
    [UIView animateWithDuration:0.5 animations:^{
        UIEdgeInsets inset = self.scrollView.contentInset;
        inset.top = 0.f;
        self.scrollView.contentInset = inset;
    } completion:^(BOOL finished) {
        [self.thirdPointLayer removeAllAnimations];
        [self.firstPointLayer removeAllAnimations];
        [self.secondPointLayer removeAllAnimations];
        self.isAnimating = NO;
    }];
}

本文借鑒:http://www.reibang.com/p/3c51e4896632
demo:https://github.com/SionChen/CYXBossRefreshDemo/tree/master 歡迎討論

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末壳繁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子荔棉,更是在濱河造成了極大的恐慌闹炉,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件润樱,死亡現(xiàn)場離奇詭異渣触,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)壹若,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門嗅钻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人店展,你說我怎么就攤上這事养篓。” “怎么了赂蕴?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵柳弄,是天一觀的道長。 經(jīng)常有香客問我概说,道長碧注,這世上最難降的妖魔是什么嚣伐? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮应闯,結(jié)果婚禮上纤控,老公的妹妹穿的比我還像新娘挂捻。我一直安慰自己碉纺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布刻撒。 她就那樣靜靜地躺著骨田,像睡著了一般。 火紅的嫁衣襯著肌膚如雪声怔。 梳的紋絲不亂的頭發(fā)上态贤,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音醋火,去河邊找鬼悠汽。 笑死,一個胖子當(dāng)著我的面吹牛芥驳,可吹牛的內(nèi)容都是我干的柿冲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼兆旬,長吁一口氣:“原來是場噩夢啊……” “哼假抄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起丽猬,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤宿饱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后脚祟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谬以,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年由桌,在試婚紗的時候發(fā)現(xiàn)自己被綠了为黎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡沥寥,死狀恐怖碍舍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情邑雅,我是刑警寧澤片橡,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站淮野,受9級特大地震影響捧书,放射性物質(zhì)發(fā)生泄漏吹泡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一经瓷、第九天 我趴在偏房一處隱蔽的房頂上張望爆哑。 院中可真熱鬧,春花似錦舆吮、人聲如沸揭朝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽潭袱。三九已至,卻和暖如春锋恬,著一層夾襖步出監(jiān)牢的瞬間屯换,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工与学, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留彤悔,地道東北人。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓索守,卻偏偏與公主長得像晕窑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蕾盯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353