iOS开发-自定义下拉刷新控件PullDownRefreshView

iOS开发-自定义下拉刷新控件PullDownRefreshView

在开发过程中,有时候需要自定义下拉刷新控件,这时候我们就需要自定义PullDownRefreshView。

PullDownRefreshView是在UIScrollView上。
在这里插入图片描述

一、UIScrollView

在下拉刷新过程中,需要实现UIScrollView的delegate的相关方法

// 拖动过程中

  • (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
  • (void)scrollViewDidScroll:(UIScrollView *)scrollView;
  • (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;

三个方法调用顺序

  • 先执行scrollViewWillBeginDragging:,将要开始拖拽
  • 然后执行n个scrollViewDidScroll,只要是scrollView的contentOffset发生改变就会执行,无论是通过手动拖拽还是代码改变了contentOffset
  • 最后执行scrollViewDidEndDragging:willDecelerate:,拖拽结束,因为没有减速滑动,所以此时也是scrollView最终停止位置

二、实现下拉刷新PullDownRefreshView

在下拉过程中显示,我们需要将refreshView初始化

- (SDPullDownRefreshView *)refreshView {
    if (!_refreshView) {
        _refreshView = [[SDPullDownRefreshView alloc] initWithFrame:CGRectMake(0.0, 0.0, CGRectGetWidth([UIScreen mainScreen].bounds), 80)];
    }
    return _refreshView;
}

配置下拉刷新

- (void)configRefresh {
    [self.refreshView setupWithOwner:self.noticationView.tableView delegate:self];
}

实现UIScrollView的Delegate的相关方法

- (void)pullDownRefreshDidFinish {
    [self performSelector:@selector(stop) withObject:nil afterDelay:1];
}

- (void)stopLoading {
    [self.refreshView stopLoading];
}

- (void)stop {
    [self stopLoading];
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    [self.refreshView scrollViewWillBeginDragging:scrollView];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    [self.refreshView scrollViewDidScroll:scrollView];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    [self.refreshView scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
}

整体SDPullDownRefreshView的完整代码

SDPullDownRefreshView.h

#import <UIKit/UIKit.h>

@protocol SDPullDownRefreshViewDelegate;

@interface SDPullDownRefreshView : UIView {
    BOOL isDragging;
    BOOL isLoading;
}

@property (nonatomic, weak) id delegate;
@property (nonatomic, weak) UIScrollView *owner;
@property (nonatomic, strong) UILabel *refreshLabel;
@property (nonatomic, strong) UIActivityIndicatorView *refreshSpinner;

- (void)setupWithOwner:(UIScrollView *)owner delegate:(id<SDPullDownRefreshViewDelegate>)delegate;

- (void)startLoading;
- (void)stopLoading;

// 拖动过程中
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;

@end

@protocol SDPullDownRefreshViewDelegate <NSObject>

- (void)pullDownRefreshDidFinish;

@end

SDPullDownRefreshView.m

#import "SDPullDownRefreshView.h"

#define REFRESH_PULL_UP_STATUS @"下拉可以回到上面"
#define REFRESH_RELEASED_STATUS @"可以松开了"
// 加载中
#define REFRESH_LOADING_STATUS @""
#define REFRESHER_HEIGHT 50.0f

@interface SDPullDownRefreshView ()

@end

@implementation SDPullDownRefreshView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor clearColor];
        
        self.clipsToBounds = YES;
        
        self.refreshLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, REFRESHER_HEIGHT)];
        self.refreshLabel.backgroundColor = [UIColor clearColor];
        self.refreshLabel.font = [UIFont boldSystemFontOfSize:12.0];
        self.refreshLabel.textAlignment = NSTextAlignmentCenter;
        
        self.refreshSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        self.refreshSpinner.frame = CGRectMake((frame.size.width - 20)/2, (REFRESHER_HEIGHT - 20)/2, 20, 20);
        self.refreshSpinner.hidesWhenStopped = YES;
        
        [self addSubview:self.refreshLabel];
        [self addSubview:self.refreshSpinner];
    }
    return self;
}

- (void)layout:(CGPoint)offset {
    if (offset.y < 0) {
        [self setFrame:CGRectMake(0, 0 - REFRESHER_HEIGHT, self.frame.size.width, REFRESHER_HEIGHT)];
        self.refreshLabel.frame = CGRectMake(0, 0, self.frame.size.width, REFRESHER_HEIGHT);
        self.refreshSpinner.frame = CGRectMake((self.frame.size.width - 20)/2, (REFRESHER_HEIGHT - 20)/2, 20, 20);

    } else {
        [self setFrame:CGRectMake(0, -REFRESHER_HEIGHT, self.frame.size.width, 0)];
        self.refreshLabel.frame = CGRectMake(0, 0, self.frame.size.width, REFRESHER_HEIGHT);
        self.refreshSpinner.frame = CGRectMake((self.frame.size.width - 20)/2, (REFRESHER_HEIGHT - 20)/2, 20, 20);
    }
}


- (void)setupWithOwner:(UIScrollView *)owner  delegate:(id)delegate {
    self.owner = owner;
    self.delegate = delegate;
    
    [_owner addSubview:self];
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    if (isLoading) {
        return;
    }
    isDragging = YES;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    CGPoint offset = scrollView.contentOffset;
    [self layout:offset];
    
    if (isLoading && offset.y > 0) {
        return;
    }
    
    if (isDragging && offset.y <= 0 ) {
        
        [self.refreshSpinner stopAnimating];
        // Update the arrow direction and label
        if (scrollView.contentOffset.y <= -REFRESHER_HEIGHT) {
            // User is scrolling above the header
            self.refreshLabel.text = REFRESH_RELEASED_STATUS;
        } else {
            // User is scrolling somewhere within the header
            self.refreshLabel.text = REFRESH_PULL_UP_STATUS;
        }
    }
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (isLoading) return;
    isDragging = NO;
    
    // 上拉刷新
    if(scrollView.contentOffset.y <= -REFRESHER_HEIGHT){
        [self startLoading];
    }
}


- (void)startLoading
{
    if (isLoading) {
        return;
    }
    isLoading = YES;
    
    UIEdgeInsets contentInset = self.owner.contentInset;
    contentInset.top = REFRESHER_HEIGHT;
    self.refreshLabel.text = REFRESH_LOADING_STATUS;

    [UIView animateWithDuration:0.25 animations:^{
        self.owner.contentInset = contentInset;
        [self.refreshSpinner startAnimating];
    } completion:^(BOOL finished) {
        // Refresh action!
        if ([self.delegate respondsToSelector:@selector(pullDownRefreshDidFinish)]) {
            [self.delegate performSelector:@selector(pullDownRefreshDidFinish) withObject:nil];
        }
    }];
}

- (void)stopLoading {
    isLoading = NO;
    
    UIEdgeInsets contentInset = self.owner.contentInset;
    contentInset.top = 0.0;
    [UIView animateWithDuration:0.15 animations:^{
        self.owner.contentInset = contentInset;
    } completion:^(BOOL finished) {
        
        // Reset the header        
        self.refreshLabel.text = REFRESH_PULL_UP_STATUS;
        
        [self setFrame:CGRectMake(0, -REFRESHER_HEIGHT, self.frame.size.width, 0)];
        [self.refreshSpinner stopAnimating];
    }];
}

@end


三、小结

iOS开发-自定义下拉刷新控件PullDownRefreshView

学习记录,每天不停进步。

猜你喜欢

转载自blog.csdn.net/gloryFlow/article/details/134059343