分析 表视图上拉刷新的思路
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