UITableView之上拉刷新

本文深入探讨了表视图上拉刷新的功能原理,并详细解释了实现过程,包括视图封装、状态切换及数据加载逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分析 表视图上拉刷新的思路
1.当上拉刷新的时候,底部那个显示刷新样式的是什么东西?
<1.会不会是tableFooterView  ?
	不会,因为tableFooterView是表视图的内容。 如果用tableFooterView的话,我们怎么完成反弹加载数据的效果?
<2.封装视图?
	必须要自己封装一个视图,并且因为刷新视图有图有label,用button就好
2.怎么封装呢?
刷新一共三步
<1.上拉加载更多
<2.在某一程度上是 松开加载更多
<3.读取中…

什么时候显示上拉加载更多呢?这个视图怎么封装?
0.建立容器视图
1.我们首先将视图放在表视图最底
2.当表视图的偏移量到了一定范围我们将视图显示为上拉加载更多
3.超过一定范围,则显示为松开加载更多,结束拖拽,则加载
4.此时显示读取中 ,刷新数据<pre name="code" class="objc">#import "YXFreshFooterView.h"

@interface YXFreshFooterView ()
@property (nonatomic,weak) UIButton *alertButton;
@property (nonatomic,weak) UIView *activityView;
@end

@implementation YXFreshFooterView

+ (id)freshFooterView {
    return [[self alloc] init];
}

// 设置刷新视图的frame 根据tableView来设置
- (void)willMoveToSuperview:(UIView *)newSuperview {
    
    UITableView *tableView = (UITableView *)newSuperview;
    self.y = tableView.contentSize.height;
    self.width = tableView.width;
    self.height = 60;
    self.backgroundColor = [UIColor lightGrayColor];
}
/**
 *  底部刷新视图的状态
 */
- (void)setFreshFooterViewStatus:(FreshFooterViewStatus)freshFooterViewStatus {
    
    _freshFooterViewStatus = freshFooterViewStatus;
    
    switch (freshFooterViewStatus) {
            
            // 更换状态时,设置标题和旋转
        case FreshFooterViewStatusDragging:
            [self.alertButton setTitle:@"拖拽加载更多" forState:UIControlStateNormal];
            self.alertButton.imageView.transform = CGAffineTransformMakeRotation(M_PI);
            break;
            
        case FreshFooterViewStatusEndDragging: {
            [self.alertButton setTitle:@"松开读取更多" forState:UIControlStateNormal];
            [UIView animateWithDuration:0.3 animations:^{
                // 使图形的形变恢复到最开始的状态
                self.alertButton.imageView.transform = CGAffineTransformIdentity;
            }];
        }
            break;
            
        case FreshFooterViewStatusLoading:
            self.alertButton.hidden = YES;
            [self activityView];
            break;
            
        default:
            break;
    }
}

#pragma mark - 懒加载
- (UIButton *)alertButton {
    if (_alertButton == nil) {
        UIButton *alertButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [self addSubview:alertButton];
        // 保存全局变量
        _alertButton = alertButton;
        alertButton.frame = self.bounds;
        // 设置图片
        [alertButton setImage:[UIImage imageNamed:@"arrow"] forState:UIControlStateNormal];
        // 关闭用户交互
        alertButton.userInteractionEnabled = NO;
        alertButton.titleLabel.font = [UIFont systemFontOfSize:13];
        // 调节上下左右边距 - > 设置小图标与文字的距离
        alertButton.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 60);
        // 这是系统提供的宏定义,专门用来表示π 的关系
        alertButton.imageView.transform = CGAffineTransformMakeRotation(M_PI);
        // 使用形变属性,让image图标旋转180度
        // UIButton 为什么可以显示文字? UILabel
        // UIButton 为什么可以显示图片? UIImageView
        // UIButton 为什么能够响应用户的点击事件呢? UIControl addTarget...
        // UIButton 它的设计原则是什么呢?
        // 如何更好的管理这些复杂的子控件之间的关系呢?
        // 尽量以整体作为管理的思想进行设计,然后对外流出多种管理接口,可以整体管理的接口(属性),可以单独管理的接口(属性)
    }
    return _alertButton;
}


- (UIView *)activityView {
    if (_activityView == nil) {
        
        // 容器视图
        UIView *tmpView = [[UIView alloc] init];
        // 菊花 + label
        [self addSubview:tmpView];
        _activityView = tmpView;
        tmpView.frame = self.bounds;
        
        UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] init];
        // 加上菊花
        [tmpView addSubview:activityIndicatorView];
        activityIndicatorView.x = 20;
        activityIndicatorView.y = 30;
        // 改变指示器的风格
        activityIndicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;

        // 启动菊花动画
        [activityIndicatorView startAnimating];
        
        // 加上label
        UILabel *titleLabel = [[UILabel alloc] init];
        [tmpView addSubview:titleLabel];
        titleLabel.text = @"读取中...";
        titleLabel.frame = CGRectMake(60, 10, 100, 30);

    }
    return _activityView;
}
@end


#import "YXFreshFooterView.h"

@interface YXFreshFooterView ()
@property (nonatomic,weak) UIButton *alertButton;
@property (nonatomic,weak) UIView *activityView;
@end

@implementation YXFreshFooterView

+ (id)freshFooterView {
    return [[self alloc] init];
}

// 设置刷新视图的frame 根据tableView来设置
- (void)willMoveToSuperview:(UIView *)newSuperview {
    
    UITableView *tableView = (UITableView *)newSuperview;
    self.y = tableView.contentSize.height;
    self.width = tableView.width;
    self.height = 60;
    self.backgroundColor = [UIColor lightGrayColor];
}
/**
 *  底部刷新视图的状态
 */
- (void)setFreshFooterViewStatus:(FreshFooterViewStatus)freshFooterViewStatus {
    
    _freshFooterViewStatus = freshFooterViewStatus;
    
    switch (freshFooterViewStatus) {
            
            // 更换状态时,设置标题和旋转
        case FreshFooterViewStatusDragging:
            [self.alertButton setTitle:@"拖拽加载更多" forState:UIControlStateNormal];
            self.alertButton.imageView.transform = CGAffineTransformMakeRotation(M_PI);
            break;
            
        case FreshFooterViewStatusEndDragging: {
            [self.alertButton setTitle:@"松开读取更多" forState:UIControlStateNormal];
            [UIView animateWithDuration:0.3 animations:^{
                // 使图形的形变恢复到最开始的状态
                self.alertButton.imageView.transform = CGAffineTransformIdentity;
            }];
        }
            break;
            
        case FreshFooterViewStatusLoading:
            self.alertButton.hidden = YES;
            [self activityView];
            break;
            
        default:
            break;
    }
}

#pragma mark - 懒加载
- (UIButton *)alertButton {
    if (_alertButton == nil) {
        UIButton *alertButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [self addSubview:alertButton];
        // 保存全局变量
        _alertButton = alertButton;
        alertButton.frame = self.bounds;
        // 设置图片
        [alertButton setImage:[UIImage imageNamed:@"arrow"] forState:UIControlStateNormal];
        // 关闭用户交互
        alertButton.userInteractionEnabled = NO;
        alertButton.titleLabel.font = [UIFont systemFontOfSize:13];
        // 调节上下左右边距 - > 设置小图标与文字的距离
        alertButton.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 60);
        // 这是系统提供的宏定义,专门用来表示π 的关系
        // 使用形变属性,让image图标旋转180度
        // UIButton 为什么可以显示文字? UILabel
        // UIButton 为什么可以显示图片? UIImageView
        // UIButton 为什么能够响应用户的点击事件呢? UIControl addTarget...
        // UIButton 它的设计原则是什么呢?
        // 如何更好的管理这些复杂的子控件之间的关系呢?
        // 尽量以整体作为管理的思想进行设计,然后对外流出多种管理接口,可以整体管理的接口(属性),可以单独管理的接口(属性)
    }
    return _alertButton;
}


- (UIView *)activityView {
    if (_activityView == nil) {
        
        // 容器视图
        UIView *tmpView = [[UIView alloc] init];
        // 菊花 + label
        [self addSubview:tmpView];
        _activityView = tmpView;
        tmpView.frame = self.bounds;
        
        UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] init];
        // 加上菊花
        [tmpView addSubview:activityIndicatorView];
        activityIndicatorView.x = 20;
        activityIndicatorView.y = 30;
        // 改变指示器的风格
        activityIndicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;

        // 启动菊花动画
        [activityIndicatorView startAnimating];
        
        // 加上label
        UILabel *titleLabel = [[UILabel alloc] init];
        [tmpView addSubview:titleLabel];
        titleLabel.text = @"读取中...";
        titleLabel.frame = CGRectMake(60, 10, 100, 30);

    }
    return _activityView;
}
@end


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值