zoukankan      html  css  js  c++  java
  • IOS UITableView下拉刷新和上拉加载功能的实现

      在IOS开发中UITableView是非常常用的一个功能,而在使用UITableView的时候我们经常要用到下拉刷新和上拉加载的功能,今天花时间实现了简单的UITableView的下拉刷新和上拉加载功能,效果图如下:

     

      代码如下:

    TableRefreshHeaderView.h

    #import <UIKit/UIKit.h>
    
    @interface TableRefreshHeaderView : UIView
    
    @property(nonatomic, strong)UIImageView *arrowView;
    
    @property(nonatomic, strong)UILabel *refreshText;
    
    @property(nonatomic, strong)UIActivityIndicatorView *loadingIndicatorView;
    
    -(instancetype)initWithFrame:(CGRect)frame;
    
    - (void)setRefreshMode:(int)mode;
    
    @end

    TableRefreshHeaderView.m

    #import "TableRefreshHeaderView.h"
    
    #define UISCREEN_WIDTH [UIScreen mainScreen ].bounds.size.width
    #define UISCREEN_HEIGHT [UIScreen mainScreen ].bounds.size.height
    
    @implementation TableRefreshHeaderView
    
    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    - (void)drawRect:(CGRect)rect {
        // Drawing code
    }
    */
    
    -(instancetype)initWithFrame:(CGRect)frame;
    {
        self = [super initWithFrame:frame];
        if (self) {
            [self addSubview:self.arrowView];
            [self addSubview:self.refreshText];
            [self addSubview:self.loadingIndicatorView];
            self.loadingIndicatorView.hidden = YES;
        }
        return self;
        
    }
    
    //箭头图片UIImageView
    -(UIImageView *)arrowView
    {
        if (!_arrowView) {
            _arrowView = [[UIImageView alloc]initWithFrame:CGRectMake(UISCREEN_WIDTH / 2.0 - 60, 0, 15, 30)];
            _arrowView.image = [UIImage imageNamed:@"arrow"];
        }
        return _arrowView;
    }
    
    //下拉刷新文字
    -(UILabel *)refreshText
    {
        if (!_refreshText) {
            _refreshText = [[UILabel alloc]initWithFrame:CGRectMake(UISCREEN_WIDTH / 2.0 - 15, 0, 75, 30)];
            _refreshText.font = [UIFont fontWithName:@"Arial" size:14];
            _refreshText.textColor = [UIColor blackColor];
            _refreshText.text = @"下拉刷新";
        }
        return _refreshText;
    }
    
    //刷新旋转视图
    - (UIActivityIndicatorView *)loadingIndicatorView
    {
        if (!_loadingIndicatorView) {
            _loadingIndicatorView = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(UISCREEN_WIDTH / 2.0 - 65, 2, 25, 25)];
            [_loadingIndicatorView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
            _loadingIndicatorView.backgroundColor = [UIColor clearColor];
            _loadingIndicatorView.center = CGPointMake(UISCREEN_WIDTH / 2.0 - 52, 14);
        }
        return _loadingIndicatorView;
    }
    
    //设置三种刷新模式
    - (void)setRefreshMode:(int)mode
    {
        switch (mode) {
            case 1://下拉过程中
            {
                self.arrowView.hidden = NO;
                self.loadingIndicatorView.hidden = YES;
                [self.loadingIndicatorView stopAnimating];
                [UIView animateWithDuration:0.3 animations:^(void){
                    _arrowView.transform = CGAffineTransformMakeRotation(M_PI * 2);
                }];
                self.refreshText.text = @"下拉刷新";
            }
                break;
            case 2://提示松开刷新
            {
                self.arrowView.hidden = NO;
                self.loadingIndicatorView.hidden = YES;
                [self.loadingIndicatorView stopAnimating];
                [UIView animateWithDuration:0.3 animations:^(void){
                    _arrowView.transform = CGAffineTransformMakeRotation(M_PI);
                }];
                self.refreshText.text = @"松开刷新";
            }
                break;
            case 3://松开后刷新
            {
                self.arrowView.hidden = YES;
                self.loadingIndicatorView.hidden = NO;
                [self.loadingIndicatorView startAnimating];
                self.refreshText.text = @"正在刷新";
                
            }
                break;
                
            default:
                break;
        }
    }
    
    
    @end

    TableRefreshFooterView.h

    #import <UIKit/UIKit.h>
    
    @interface TableRefreshFooterView : UIView
    
    @property(nonatomic, strong) UIActivityIndicatorView *loadingIndcatorView;
    
    @property(nonatomic, strong) UILabel *loadingText;
    
    - (void)setLoadingMode:(int)mode;
    
    @end

    TableRefreshFooterView.m

    #import "TableRefreshFooterView.h"
    
    #define UISCREEN_WIDTH [UIScreen mainScreen ].bounds.size.width
    #define UISCREEN_HEIGHT [UIScreen mainScreen ].bounds.size.height
    
    @implementation TableRefreshFooterView
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            [self addSubview:self.loadingIndcatorView];
            [self addSubview:self.loadingText];
        }
        return self;
    }
    
    - (UIActivityIndicatorView *)loadingIndcatorView
    {
        if (!_loadingIndcatorView) {
            _loadingIndcatorView = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(UISCREEN_WIDTH / 2.0 - 65, 2, 25, 25)];
            [_loadingIndcatorView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
            _loadingIndcatorView.backgroundColor = [UIColor clearColor];
            _loadingIndcatorView.center = CGPointMake(UISCREEN_WIDTH / 2.0 - 52, 14);
        }
        return _loadingIndcatorView;
    }
    
    - (UILabel *)loadingText
    {
        if (!_loadingText) {
            _loadingText = [[UILabel alloc]initWithFrame:CGRectMake(UISCREEN_WIDTH / 2.0 - 15, 0, 75, 30)];
            _loadingText.font = [UIFont fontWithName:@"Arial" size:14];
            _loadingText.textColor = [UIColor blackColor];
            _loadingText.text = @"加载中";
        }
        return _loadingText;
    }
    
    - (void)setLoadingMode:(int)mode
    {
        switch (mode) {
            case 1:
                _loadingText.text = @"加载中";
                [self.loadingIndcatorView startAnimating];
                self.loadingIndcatorView.hidden = NO;
                break;
                case 2:
                _loadingText.text = @"加载完毕";
                [self.loadingIndcatorView stopAnimating];
                self.loadingIndcatorView.hidden = YES;
                break;
            default:
                break;
        }
    }
    
    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    - (void)drawRect:(CGRect)rect {
        // Drawing code
    }
    */
    
    
    
    @end

    ViewController.h

    #import <UIKit/UIKit.h>
    #import "TableRefreshHeaderView.h"
    #import "TableRefreshFooterView.h"
    
    @interface ViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
    {
        int rowCount;//行数
        BOOL isLoading;//是否正在加载
        BOOL isRefreshing;//是否正在刷新
        int drageMode;//1为下拉刷新,2为上拉加载
    }
    
    @property(nonatomic, strong)UITableView *myTableView;
    
    @property(nonatomic, strong)TableRefreshHeaderView *refreshHeaderView;
    
    @property(nonatomic, strong)TableRefreshFooterView *loadingFooterView;
    
    @end

    ViewController.m

    #import "ViewController.h"
    #define UISCREEN_WIDTH [UIScreen mainScreen ].bounds.size.width
    #define UISCREEN_HEIGHT [UIScreen mainScreen ].bounds.size.height
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        rowCount = 20;
        isLoading = NO;
        isRefreshing = NO;
        drageMode = -1;
        [self.view addSubview:self.myTableView];
        [self.myTableView addSubview:self.refreshHeaderView];
        [self.myTableView addSubview:self.loadingFooterView];
        [self.myTableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
        
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    - (void)dealloc
    {
        [self.myTableView removeObserver:self forKeyPath:@"contentOffset"];
    }
    
    - (UITableView *)myTableView
    {
        if (!_myTableView) {
            _myTableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 50, UISCREEN_WIDTH, UISCREEN_HEIGHT - 50)];
            _myTableView.delegate = self;
            _myTableView.dataSource = self;
        }
        return _myTableView;
    }
    
    - (TableRefreshHeaderView *)refreshHeaderView
    {
        if (!_refreshHeaderView) {
            _refreshHeaderView = [[TableRefreshHeaderView alloc]initWithFrame:CGRectMake(0, -30, UISCREEN_WIDTH, 30)];
        }
        return _refreshHeaderView;
    }
    
    - (TableRefreshFooterView *)loadingFooterView
    {
        if (!_loadingFooterView) {
            _loadingFooterView = [[TableRefreshFooterView alloc]initWithFrame:CGRectMake(0, self.myTableView.contentSize.height, UISCREEN_WIDTH, 30)];
        }
        return _loadingFooterView;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return rowCount;
    }
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return 1;
    }
    
    - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
        }
        cell.textLabel.text=[NSString stringWithFormat:@"%ld",indexPath.row+1];
        return cell;
    }
    
    -(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
    {
        //如果列表控件加载完毕且当前为下拉加载,则将下拉加载视图移到列表可视范围之外
        if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row && drageMode == 2){
            self.myTableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
        }
    }
    
    //监听UITableview的顶部和头部下拉事件
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
    {
        if ([keyPath isEqualToString:@"contentOffset"] && !isLoading && !isRefreshing) {
            self.loadingFooterView.frame = CGRectMake(0, self.myTableView.contentSize.height, UISCREEN_WIDTH, 30);
            if (self.myTableView.isDragging) {
                if (self.myTableView.contentOffset.y > -45) {
                    [self.refreshHeaderView setRefreshMode:1];
                }
                else if (self.myTableView.contentOffset.y < -45)
                {
                    [self.refreshHeaderView setRefreshMode:2];
                }
            }
            else
            {
                if (self.myTableView.contentOffset.y < -45)
                {
                    drageMode = 1;
                    self.myTableView.contentInset = UIEdgeInsetsMake(45, 0, 0, 0);
                    [self.refreshHeaderView setRefreshMode:3];
                    [self beginRefresh];
                }
                else if (self.myTableView.contentOffset.y  > self.myTableView.contentSize.height - self.myTableView.frame.size.height + 45)
                {
                    drageMode = 2;
                        if (rowCount < 50) {
                        [self.loadingFooterView setLoadingMode:1];
                        [self beginLoading];
                    }
                    else
                    {
                        [self.loadingFooterView setLoadingMode:2];
                        self.myTableView.contentInset = UIEdgeInsetsMake(0, 0, 45, 0);
                    }
                }
            }
        }
    }
    
    //开始刷新
    - (void)beginRefresh
    {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            isRefreshing = YES;
            sleep(2);//处理耗时操作
            dispatch_async(dispatch_get_main_queue(), ^{
                [self endRefresh];//处理完之后更新界面
            });
        }) ;
    }
    
    //停止刷新
    - (void)endRefresh
    {
        [UIView animateWithDuration:0.3 animations:^{
            self.myTableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
        }];
        [self.refreshHeaderView setRefreshMode:1];
        isRefreshing = NO;
    }
    
    //开始加载
    - (void)beginLoading
    {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
                isLoading = YES;
                rowCount += 10;
                self.myTableView.contentInset = UIEdgeInsetsMake(0, 0, 45, 0);
                sleep(2);//处理耗时操作
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.myTableView reloadData];
                [self endLoading];//处理完之后更新界面
            });
        }) ;
    }
    
    //停止加载
    - (void)endLoading
    {
        if (rowCount >= 50) {
            [self.loadingFooterView setLoadingMode:2];
            self.myTableView.contentInset = UIEdgeInsetsMake(0, 0, 45, 0);
        }
        else
        {
            self.myTableView.contentInset = UIEdgeInsetsMake(0, 0, 45, 0);
            [self.loadingFooterView setLoadingMode:1];
        }
        isLoading = NO;
    }
    
    @end

    源码下载地址:http://download.csdn.net/detail/lzm2625347497/9601843

  • 相关阅读:
    hive之窗口函数
    linux环境下Mysql的卸载和重新安装和启动
    2017ACM暑期多校联合训练
    2017ACM暑期多校联合训练
    状态压缩dp
    铺砖问题 (状态压缩dp)
    POj 2104 K-th Number (分桶法+线段树)
    POJ 2991 Crane (线段树)
    4 Values whose Sum is 0 POJ 2785 (折半枚举)
    Billboard HDU 2795 (线段树)
  • 原文地址:https://www.cnblogs.com/lzmfywz/p/5765137.html
Copyright © 2011-2022 走看看