iOS自定義下拉刷新控件--保持刷新動畫位置不變

說到下拉刷新我想都會想到MJRefresh,雖然它很強大,但是有些需求還是辦不到,只能自定義.如下圖:



下拉2.gif

MJRefresh是將動畫圖片放在scrollview的頂部,使動畫圖片與scrollview在同一級,并且隨著scrollview的滑動而滑動.而上圖中的效果是將動畫放在視圖控制器上,并且在tableview上面,而且根據(jù)tableview滑動改變透明度.
我的思路大概是這樣的:

1.這個自定義的View能隨著scrollview滑動而改變自身的狀態(tài),并且它的X需要在scrollview的中間,Y在scrollview下面一點那么說明View需要持有scrollview,.

2.在View里面監(jiān)聽ScrollView的contentOffset屬性,來做相應(yīng)的處理.

3.刷新狀態(tài)大致分為閑置狀態(tài),正在刷新和結(jié)束刷新3種.

4.正在刷新的時候需要改變scrollView的contentInset,并在刷新結(jié)束后恢復(fù).

好了,沿著這個思路開干吧,代碼量非常少,只有一個文件.

MHRefreshHeader.h

#import <UIKit/UIKit.h>
UIKIT_EXTERN NSString *const BaseRefreshViewObserveKeyPath;
typedef enum {
    MHRefreshStateNormal,//閑置狀態(tài)
    MHRefreshStateRefreshing,//正在刷新
    MHRefreshStateEndRresh,//結(jié)束刷新
} MHRefreshViewState;
@interface MHRefreshHeader : UIView
@property (nonatomic, copy) void(^refreshingBlock)(void);
@property(nonatomic,strong) UIImageView *refreshImageView;
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, assign) MHRefreshViewState refreshState;

- (void)endRefreshing;
+(instancetype)refreshWithScroll:(UIScrollView *)scrollView;
@end

MHRefreshHeader.m

#import "MHRefreshHeader.h"
#import "UIView+Additions.h"
static const CGFloat RefreshMinY = - 64.f;

NSString *const BaseRefreshViewObserveKeyPath = @"contentOffset";
@implementation MHRefreshHeader

//使點擊穿透
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    return nil;
}
+(instancetype)refreshWithScroll:(UIScrollView *)scrollView
{
    MHRefreshHeader *header = [MHRefreshHeader new];
    header.centerX = scrollView.centerX;
    header.y = scrollView.y;
    header.scrollView = scrollView;
    [scrollView.superview addSubview:header];
    return header;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        [self setupView];
    }
    return self;
}
- (void)setScrollView:(UIScrollView *)scrollView
{
    _scrollView = scrollView;
    //添加監(jiān)聽
    [scrollView addObserver:self forKeyPath:BaseRefreshViewObserveKeyPath options:NSKeyValueObservingOptionNew context:nil];
}

- (void)willMoveToSuperview:(UIView *)newSuperview
{
    if (!newSuperview) {
        [self.scrollView removeObserver:self forKeyPath:BaseRefreshViewObserveKeyPath];
    }
}

-(void)endRefreshing
{
    self.refreshState = MHRefreshStateEndRresh;
}
//初始化圖片
- (void)setupView
{
    self.backgroundColor = [UIColor clearColor];
    _refreshImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"loading_1"]];
    NSMutableArray *refreshingImages = [NSMutableArray array];
    for (NSUInteger i = 1; i < 6; i++) {
        UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"loading_%zd", i]];
        [refreshingImages addObject:image];
    }
    _refreshImageView.animationImages = refreshingImages;
    self.bounds = _refreshImageView.bounds;
    [self addSubview:_refreshImageView];
    _refreshImageView.alpha = 0;
    self.refreshState = MHRefreshStateNormal;
}
//刷新狀態(tài)改變
- (void)setRefreshState:(MHRefreshViewState)refreshState
{
    
    if (refreshState == MHRefreshStateRefreshing) {
        if (self.refreshingBlock) {
            self.refreshingBlock();
        }
        [_refreshImageView startAnimating];
        [UIView animateWithDuration:0.3 animations:^{
            self.scrollView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
        }];
    } else if (refreshState == MHRefreshStateNormal) {
        if (_refreshImageView.isAnimating) {
            [_refreshImageView stopAnimating];
            self.scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
        }
    }else if (refreshState == MHRefreshStateEndRresh){
        if (_refreshImageView.isAnimating) {
            [_refreshImageView stopAnimating];
            [UIView animateWithDuration:0.3 animations:^{
                self.scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
            }];
        }
    }
}

//改變透明度
-(void)setPullingPercent:(CGFloat)percent
{
    _refreshImageView.alpha = percent;
}

//滑動處理
- (void)updateRefreshHeaderWithOffsetY:(CGFloat)y
{
    if (y > 0) {//防止往上劃的時候動圖顯示出來
        return;
    }
    [self setPullingPercent:(fabs(y) - 20) / (fabs(RefreshMinY) - 20)];
    if (self.refreshState == MHRefreshStateRefreshing) {
        return;
    }
    if (y < RefreshMinY) {
        if(!self.scrollView.isDragging ){
            self.refreshState = MHRefreshStateRefreshing;
        }
    }else{
        if (self.refreshState == MHRefreshStateNormal) {
            return;
        }
        self.refreshState = MHRefreshStateNormal;
    }
    
}
//監(jiān)聽滑動
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
    if (keyPath != BaseRefreshViewObserveKeyPath) return;
    
    [self updateRefreshHeaderWithOffsetY:self.scrollView.contentOffset.y];
}

@end

是不是很簡單呀?
然后再看看使用

 _refreshHeader = [MHRefreshHeader refreshWithScroll:_tableView];
    __weak typeof(self) weakSelf = self;
    [_refreshHeader setRefreshingBlock:^{
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [weakSelf.refreshHeader endRefreshing];
        });
    }];

只有2步,通過scrollview創(chuàng)建,然后在刷新方法里面結(jié)束刷新.給大家提供個思路,有更好的辦法歡迎留言交流??
github地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末茂翔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子则吟,更是在濱河造成了極大的恐慌,老刑警劉巖娇妓,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒿秦,死亡現(xiàn)場離奇詭異,居然都是意外死亡乍构,警方通過查閱死者的電腦和手機周崭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門柳譬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人续镇,你說我怎么就攤上這事美澳。” “怎么了摸航?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵制跟,是天一觀的道長。 經(jīng)常有香客問我酱虎,道長雨膨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任读串,我火速辦了婚禮聊记,結(jié)果婚禮上撒妈,老公的妹妹穿的比我還像新娘。我一直安慰自己甥雕,他們只是感情好踩身,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布胀茵。 她就那樣靜靜地躺著社露,像睡著了一般。 火紅的嫁衣襯著肌膚如雪琼娘。 梳的紋絲不亂的頭發(fā)上峭弟,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音脱拼,去河邊找鬼瞒瘸。 笑死,一個胖子當(dāng)著我的面吹牛熄浓,可吹牛的內(nèi)容都是我干的情臭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼赌蔑,長吁一口氣:“原來是場噩夢啊……” “哼俯在!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起娃惯,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤跷乐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后趾浅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體愕提,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年皿哨,在試婚紗的時候發(fā)現(xiàn)自己被綠了浅侨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡证膨,死狀恐怖如输,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情椎例,我是刑警寧澤挨决,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站订歪,受9級特大地震影響脖祈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜刷晋,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一盖高、第九天 我趴在偏房一處隱蔽的房頂上張望慎陵。 院中可真熱鬧,春花似錦喻奥、人聲如沸席纽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽润梯。三九已至,卻和暖如春甥厦,著一層夾襖步出監(jiān)牢的瞬間纺铭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工刀疙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留舶赔,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓谦秧,卻偏偏與公主長得像竟纳,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子疚鲤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 黑夜將盡锥累, 黎明將來。
    秋風(fēng)勁勁閱讀 159評論 1 4
  • 旅行就是拿到了一場艷遇的車票石咬。 我回憶起了《雪國》揩悄。開始時也是在列車上,駒子熱情地同扳道工交談鬼悠。于是删性,開始了一場埋...
    冰眉鐵面閱讀 314評論 0 0
  • 有人說過“生命從頭到尾都是一場浪費蹬挺,你需要判斷的是,這次浪費是否值得”它掂。我一直對這句話理解的都不是那么深刻巴帮,如果都...
    宋大寶不飽閱讀 441評論 1 3