iOS 自定义下拉刷新控件 —— 解决图片拉伸与数据刷新冲突

dysg0896 2年前
   <p>前言</p>    <p>iOS 的下拉刷新用的最广泛的应该是 <a href="/misc/goto?guid=4959756585464737515" rel="nofollow,noindex">MJRefresh</a> . 但是有时候不能满足我们的特殊需求. 如下拉时候, 设置的图片放大, 那么用该控件刷新就会有些问题. 今天作者 就简单封装一个 刷新控件, 仅为各位提供个思路.</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/d86080d55226e424be532930d7f22527.gif"></p>    <p>效果.gif</p>    <p>一. 控件</p>    <p>RefreshView.h文件</p>    <pre>  <code class="language-objectivec">#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  </uikit></code></pre>    <p>RefreshView.m文件</p>    <pre>  <code class="language-objectivec">#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</code></pre>    <p>二. 使用</p>    <pre>  <code class="language-objectivec">#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  </uitableviewdelegate></code></pre>    <p>以上 !</p>    <p>作者:Mr_Lucifer</p>    <p>链接:https://www.jianshu.com/p/1e9638b4e8b1</p>    <p> </p>    <p>来自:http://www.cocoachina.com/ios/20180123/21940.html</p>    <p> </p>