• 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;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    配置下拉刷新

    - (void)configRefresh {
        [self.refreshView setupWithOwner:self.noticationView.tableView delegate:self];
    }
    
    
    • 1
    • 2
    • 3
    • 4

    实现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];
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    整体SDPullDownRefreshView的完整代码

    SDPullDownRefreshView.h

    #import 
    
    @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)delegate;
    
    - (void)startLoading;
    - (void)stopLoading;
    
    // 拖动过程中
    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView;
    - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
    
    @end
    
    @protocol SDPullDownRefreshViewDelegate 
    
    - (void)pullDownRefreshDidFinish;
    
    @end
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    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
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141

    三、小结

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

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

  • 相关阅读:
    EasyGBS如何解决大屏播放时出现数据未推送情况?
    STC51单片机31——红外遥控收发代码
    PC_定点数_模+补码表示+补码相关性质
    UE4 回合游戏项目 18- 退出战斗
    【Pandas】数据分组groupby
    Jackson公司蛋白质印迹指南丨样品制备
    LeetCode热题(12.买卖股票的最佳时机)
    Git分布式版本控制工具
    vue中this.$set()的用法
    第十四届蓝桥杯模拟赛第二期部分题答案(C++代码)
  • 原文地址:https://blog.csdn.net/gloryFlow/article/details/134059343