iOS UITableView 下拉刷新果凍/彈力效果 + 自定義Refresh動畫

先上圖??Demo在最下方

效果圖.gif

這次主講下拉果凍動畫效果昂勒,自定義Refresh動畫請自行下載最下面的Demo井赌,若有算法上或者本文沒看懂的問題谤逼,可文章下面留言??
1.隱藏自身NavigationBar,自定義View作為NavigationBar完成上圖效果
2.自定義View與UITableView或者UIPanGestureRecognizer聯(lián)動
3.UIBezierPath實現(xiàn)跟隨下拉使View變形
4.松手后回彈效果(CADisplayLink實現(xiàn))

image.png

明白上面4點后仇穗,下面的內容你可能會好消化一點=流部。=

如上圖完成這個效果的重點在于用這5個點作為Path來完成一系列效果。而從Gif中不難看出仪缸,3號點是一個關鍵點贵涵,可以把它間接的理解為UIBezierPath中的ControlPoint(事實不是,后文解釋)恰画。

這里創(chuàng)建一個Layer作為容器來承載Path

@property (nonatomic, strong) CAShapeLayer *shapeLayer;

self.shapeLayer = [CAShapeLayer layer];
self.shapeLayer.fillColor = RGB(252, 157, 154).CGColor;
[self.layer addSublayer:self.shapeLayer];

然后創(chuàng)建一個ControlPoint宾茂,為了達到自然的效果,因為下拉變形距離如果跟隨手勢拖動位置直接變化會顯得很不自然拴还、突兀跨晴,所以用一個ControlPoint來比例縮小手勢拉動距離(這里再創(chuàng)建一個像素View來更直觀的看效果),并且給ControlPoint添加KVO觀察Value的變化來更新Path的變化

@property (nonatomic) CGPoint endAnimatePoint;
@property (nonatomic, strong) UIView *referencePointView;

self.referencePointView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.frame)/2.f-2, CGRectGetMaxY(self.frame)-2, 4, 4)];
self.referencePointView.backgroundColor = [UIColor redColor];
[self addSubview:self.referencePointView];

#define KVO_EndPoint @"endAnimatePoint"
- (void)setupKVO {
    [self addObserver:self forKeyPath:KVO_EndPoint options:NSKeyValueObservingOptionNew context:nil];
    self.endAnimatePoint = CGPointMake(CGRectGetWidth(self.frame)/2.f-2, CGRectGetMaxY(self.frame)-2);
}


-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:KVO_EndPoint]) {
        [self updateShapeLayerPath];
    }
}
ControlPoint.gif

從上圖可以看到ControlPoint的作用,方便理解

這里我用UITableView聯(lián)動作為例子(直接用UIPanGestureRecognizer就是這個版本的簡化)

[self.jellyTableView.panGestureRecognizer addTarget:self action:@selector(handlePanAction:)];

- (void)handlePanAction:(UIPanGestureRecognizer *)pan {
    CGPoint point = [pan translationInView:self.view];
    [self.customNavigationBar animateStateChangeAtX:point.x y:point.y];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    [self.customNavigationBar animateStateEnd];
}
- (void)animateStateChangeAtX:(CGFloat)x y:(CGFloat)y {
    if (!self.isAnimating) {
        if ((y*0.7 + CGRectGetHeight(self.frame)) > CGRectGetHeight(self.frame)) {
            //減緩手勢變化達到更自然的效果
            CGFloat mHeight = y*0.7 + CGRectGetHeight(self.frame);
            CGFloat mWidth = x + CGRectGetWidth(self.frame)/2.f;
            //改變ControlPoint的Value來執(zhí)行KVO的方法
            self.endAnimatePoint = CGPointMake(mWidth-2, mHeight-2);
            self.referencePointView.frame = CGRectMake(mWidth-2, mHeight-2, 4, 4);
            self.titleLabel.alpha = (Refresh_Height-y)/Refresh_Height;
            self.loadingAnimationView.alpha = y/Refresh_Height;
        }
        if (y > Refresh_Height) {
            self.refreshState = YES;
        }
        else {
            self.refreshState = NO;
        }
    }
    
}

接下來是果凍效果的核心代碼 注釋都在代碼里

- (void)updateShapeLayerPath {
    UIBezierPath *tPath = [UIBezierPath bezierPath];
//移動點到1
    [tPath moveToPoint:CGPointMake(0, 0)];
//連接1-5的線
    [tPath addLineToPoint:CGPointMake(CGRectGetWidth(self.frame), 0)];
//連接5-4的線
    [tPath addLineToPoint:CGPointMake(CGRectGetWidth(self.frame),  CGRectGetHeight(self.frame))];
//連接4-2的線 其中3點用ConrolPoint來作為控制點連接
    [tPath addQuadCurveToPoint:CGPointMake(0, CGRectGetHeight(self.frame)) controlPoint:CGPointMake(self.endAnimatePoint.x, self.endAnimatePoint.y)];
    [tPath closePath];
    self.shapeLayer.path = tPath.CGPath;
}

到此為止下拉已經可以看到效果了
接下來要實現(xiàn)回彈效果
這里我要用到CADisplayLink片林,這是作為跟著屏幕的刷新率更新界面UI的一個類似Timer的東西端盆,詳細屬性和作用簡書其他文章里也有很詳細的介紹,這里就不多做解釋了

@property (nonatomic, strong) CADisplayLink *displayLink;

self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updatePath:)];
self.displayLink.paused = YES;
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

- (void)updatePath:(CADisplayLink *)displayLink {
    CALayer *layer = self.referencePointView.layer.presentationLayer;
    self.endAnimatePoint = CGPointMake(layer.position.x, layer.position.y);
}
//這里我要提一嘴费封,Mode一定要選擇NSRunLoopCommonModes焕妙,原因可以自行搜索一下NSRunLoopCommonModes和NSDefaultRunLoopMode的區(qū)別,若選擇后者會導致動畫看不到或者只能看到最后一部分

這里CADisplayLink的作用就是弓摘,在我們松開手的那個刻焚鹊,拿到最后一個ControlPoint,在利用系統(tǒng)自帶的+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);方法韧献,來做一個ControlPoint回到初始位置并帶有彈性效果的動畫末患,方法中usingSpringWithDamping屬性可以理解為是用來控制彈性動畫的,這樣就可以做到隨著屏幕的刷新率锤窑,一直改變ControlPoint的位置直到回到原點動畫結束

- (void)animateStateEnd {
    if (!self.isAnimating) {
        self.isAnimating = YES;
        self.displayLink.paused = NO;
        
        [UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            self.referencePointView.frame = CGRectMake(CGRectGetWidth(self.frame)/2.f-2, CGRectGetMaxY(self.frame)-2, 4, 4);
            if (!self.refreshState) {
                self.titleLabel.alpha = 1;
                self.loadingAnimationView.alpha = 0;
            }
            else {
                self.titleLabel.alpha = 0;
                self.loadingAnimationView.alpha = 1;
            }
        } completion:^(BOOL finished) {
            if (finished) {
                self.isAnimating = NO;
                self.displayLink.paused = YES;
            }
        }];
        
        if (self.refreshState) {
            [self.loadingAnimationView startAnimate];
            [self performSelector:@selector(stopAnimate) withObject:nil afterDelay:5];
        }
    }
}

到這里位置下拉刷新果凍/彈力效果就完成了

Demo鏈接

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末璧针,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子渊啰,更是在濱河造成了極大的恐慌探橱,老刑警劉巖申屹,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異走搁,居然都是意外死亡独柑,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門私植,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人车酣,你說我怎么就攤上這事曲稼。” “怎么了湖员?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵贫悄,是天一觀的道長。 經常有香客問我娘摔,道長窄坦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任凳寺,我火速辦了婚禮鸭津,結果婚禮上,老公的妹妹穿的比我還像新娘肠缨。我一直安慰自己逆趋,他們只是感情好,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布晒奕。 她就那樣靜靜地躺著闻书,像睡著了一般。 火紅的嫁衣襯著肌膚如雪脑慧。 梳的紋絲不亂的頭發(fā)上魄眉,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音闷袒,去河邊找鬼坑律。 笑死,一個胖子當著我的面吹牛霜运,可吹牛的內容都是我干的脾歇。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼淘捡,長吁一口氣:“原來是場噩夢啊……” “哼藕各!你這毒婦竟也來了?” 一聲冷哼從身側響起焦除,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤激况,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體乌逐,經...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡竭讳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了浙踢。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绢慢。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖洛波,靈堂內的尸體忽然破棺而出胰舆,到底是詐尸還是另有隱情,我是刑警寧澤蹬挤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布缚窿,位于F島的核電站,受9級特大地震影響焰扳,放射性物質發(fā)生泄漏霜浴。R本人自食惡果不足惜抹凳,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧哥牍,春花似錦崭歧、人聲如沸顿仇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽爆雹。三九已至停蕉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間钙态,已是汗流浹背慧起。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留册倒,地道東北人蚓挤。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像驻子,于是被迫代替她去往敵國和親灿意。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內容

  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫崇呵、插件缤剧、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,102評論 4 62
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復雜域慷,今天將帶大家一窺ios動畫全貌荒辕。在這里你可以看...
    每天刷兩次牙閱讀 8,488評論 6 30
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,110評論 25 707
  • 這兩天忙得都沒時間寫簡書了汗销,心里總覺有塊心病壓著,總算是松一口氣抵窒,把心病了了弛针。 今天看到小妹發(fā)的老爸坐著輪椅在小區(qū)...
    喜歡就點個贊吧閱讀 388評論 0 0
  • 最近一段時間有很多的小伙伴分享他們求職過程中所寫的產品體驗報告削茁、競品分析等,我一邊提出一些意見掉房,一邊自己也在思考付材,...
    鎮(zhèn)雷閱讀 5,474評論 11 99