前言
iOS 的下拉刷新用的最广泛的应该是 MJRefresh. 但是有时候不能满足我们的特殊需求. 如下拉时候, 设置的图片放大, 那么用该控件刷新就会有些问题. 今天作者 就简单封装一个 刷新控件, 仅为各位提供个思路.
一. 控件
RefreshView.h文件
#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger, RefreshViewStyle) {
RefreshViewStyleNormal, // 普通状态
RefreshViewStylePulling, // 超过临界点
RefreshViewStyleLoad // 正在刷新
};
@interface RefreshView : UIView
/** 刷新控件状态 */
@property (nonatomic, assign) RefreshViewStyle refreshStyle;
/** 状态变化临界值 */
@property (nonatomic, assign) CGFloat refreshOffset;
/** 开始 */
-(void)startAnimation:(void(^)(void))start;
/** 移除 */
-(void)removeAnimation;
/**
刷新控件设置
@param scrollY 下拉值
@param isDragging 是否正在拖拽
@param load 加载刷新
*/
-(void)contentOffsetY:(CGFloat)scrollY withDragging:(BOOL)isDragging isStyleLoad:(void(^)(void))load;
@end
RefreshView.m文件
#import "RefreshView.h"
#define kWidth [UIScreen mainScreen].bounds.size.width
@interface RefreshView ()
/** 图形变化 */
@property (nonatomic, strong) UIImageView *imgView;
/** 设置加载位置 */
@property (nonatomic, assign) CGRect loadFrame;
@end
@implementation RefreshView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.loadFrame = frame;
self.imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
self.imgView.contentMode = UIViewContentModeScaleAspectFit;
self.imgView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
[self addSubview:self.imgView];
}
return self;
}
-(void)setRefreshStyle:(RefreshViewStyle)refreshStyle{
if (_refreshStyle != refreshStyle) {
_refreshStyle = refreshStyle;
}
// 根据控件状态 设置图片
switch (refreshStyle) {
case RefreshViewStyleNormal:
{
self.imgView.image = [UIImage imageNamed:@"arrow.png"];
[UIView animateWithDuration:0.2 animations:^{
self.imgView.transform = CGAffineTransformIdentity;
}];
}
break;
case RefreshViewStylePulling:
{
self.imgView.image = [UIImage imageNamed:@"arrow.png"];
[UIView animateWithDuration:0.2 animations:^{
self.imgView.transform = CGAffineTransformMakeRotation(M_PI);
}];
}
break;
case RefreshViewStyleLoad:
{
self.imgView.image = [UIImage imageNamed:@"quan.png"];
}
break;
}
}
/** 开始 */
-(void)startAnimation:(void(^)(void))start{
if (![self.imgView.layer.animationKeys containsObject:@"rotationAnimation"]) {
CABasicAnimation* rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.fromValue = [NSNumber numberWithInt:0];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 ];
rotationAnimation.duration = 0.7;
rotationAnimation.repeatCount = HUGE_VALF;
rotationAnimation.cumulative = YES;
// 切换界面 animationKeys 清空了 需要设置removedOnCompletion = NO;
rotationAnimation.removedOnCompletion = NO;
rotationAnimation.fillMode = kCAFillModeForwards;
[self.imgView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
start();
}
}
/** 移除 */
-(void)removeAnimation{
if ([self.imgView.layer.animationKeys containsObject:@"rotationAnimation"]) {
[UIView animateWithDuration:0.7 animations:^{
self.alpha = 0;
} completion:^(BOOL finished) {
self.frame = CGRectMake((kWidth - self.loadFrame.size.width) / 2, -self.loadFrame.size.height, self.loadFrame.size.width, self.loadFrame.size.height);
self.alpha = 1;
// 手动释放
[self.imgView.layer removeAnimationForKey:@"rotationAnimation"];
self.refreshStyle = RefreshViewStyleNormal;
}];
}
}
//3 刷新控件设置
-(void)contentOffsetY:(CGFloat)scrollY withDragging:(BOOL)isDragging isStyleLoad:(void(^)(void))load{
// 3.0 如何不是下拉操作 直接返回
if (scrollY < 0) {
return;
}
// 3.1 除正在刷新, 其余情况 高度跟随变化
if (self.refreshStyle != RefreshViewStyleLoad) {
self.frame = CGRectMake(self.loadFrame.origin.x, scrollY - self.loadFrame.size.height, self.loadFrame.size.width, self.loadFrame.size.height);
}
if (isDragging) { // 3.2 正在拉拽
if (scrollY >= self.refreshOffset && self.refreshStyle == RefreshViewStyleNormal) {
// 拉拽超过临界点, 修改状态为[临界拉拽]
self.refreshStyle = RefreshViewStylePulling;
}else if (scrollY < self.refreshOffset && self.refreshStyle == RefreshViewStylePulling){
// 拉拽小于临界点, 修改状态为[正常]
self.refreshStyle = RefreshViewStyleNormal;
}
} else { // 3.3 未处于拉拽状态, 并且状态为[临界拉拽]
if (self.refreshStyle == RefreshViewStylePulling) {
self.refreshStyle = RefreshViewStyleLoad;
[UIView animateWithDuration:0.2 animations:^{
self.frame = self.loadFrame;
}];
// 刷新界面
[self startAnimation:^{
load();
}];
}
}
}
@end
二. 使用
#import "ViewController.h"
#import "RefreshView.h"
#define kWidth [UIScreen mainScreen].bounds.size.width
#define kHeight [UIScreen mainScreen].bounds.size.height
static CGFloat HeaderViewHegiht = 150.0;
@interface ViewController ()<UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) UIImageView *headerView;
// 刷新控件
@property (nonatomic, strong) RefreshView *refreshView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
// 0.1 创建TableView
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, kWidth, [UIScreen mainScreen].bounds.size.height) style:UITableViewStylePlain];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:self.tableView];
self.tableView.rowHeight = 50;
if (@available(iOS 11.0, *)) {
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
// 0.2 向下偏移150
self.tableView.contentInset = UIEdgeInsetsMake(HeaderViewHegiht, 0, 0, 0);
// 0.3 添加顶部视图
self.headerView = [[UIImageView alloc] initWithFrame:CGRectMake(0, -HeaderViewHegiht, kWidth, HeaderViewHegiht)];
self.headerView.image = [UIImage imageNamed:@"huanghun.jpg"];
self.headerView.contentMode = UIViewContentModeScaleAspectFill;
[self.tableView addSubview:self.headerView];
[self creatRefreshView];
}
#pragma mark - 刷新控件
-(void)creatRefreshView{
self.refreshView = [[RefreshView alloc] initWithFrame:CGRectMake((kWidth - 30) /2, 40, 30, 30)];
[self.view insertSubview:self.refreshView aboveSubview:self.tableView];
self.refreshView.refreshStyle = RefreshViewStyleLoad;
self.refreshView.refreshOffset = 130.0;
__weak typeof(self)weakSelf = self;
[self.refreshView startAnimation:^{
[weakSelf handleData];
}];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
//1 头部背景图拉伸形变
if (scrollView.contentOffset.y < - HeaderViewHegiht) {
CGRect newHeaderFrame = self.headerView.frame;
newHeaderFrame.origin.y = scrollView.contentOffset.y;
newHeaderFrame.size.height = - scrollView.contentOffset.y;
self.headerView.frame = newHeaderFrame;
}
//2 刷新控件设置
__weak typeof(self)weakSelf = self;
CGFloat refreshOffsetY = -scrollView.contentOffset.y - HeaderViewHegiht;
[self.refreshView contentOffsetY:refreshOffsetY withDragging:scrollView.isDragging isStyleLoad:^{
[weakSelf handleData];
}];
}
-(void)handleData{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.refreshView removeAnimation];
});
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 30;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = @"identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
}
cell.textLabel.text = [NSString stringWithFormat:@"%ld", (long)indexPath.row];
return cell;
}
@end
以上 !