iOS-自定义MJRefresh下拉刷新动画
来源:互联网 发布:键盘反应速度调节软件 编辑:程序博客网 时间:2024/05/19 06:14
前段时间发现天虹旗下”红领巾”app的下拉刷新动画挺有趣,重新仿写了一个;见动画效果;
代码实现如下
MJRefreshGifHeader继承自MJ中的MJRefreshGifHeader#import "MJRefreshGifHeader.h"@interface CustomRefreshGifHeader : MJRefreshGifHeader/** 设置state状态下的动画图片images 动画持续时间duration*/- (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state;- (void)setImages:(NSArray *)images forState:(MJRefreshState)state;@end
#import "CustomRefreshGifHeader.h"#define WIDTH [UIScreen mainScreen].bounds.size.width@interface CustomRefreshGifHeader()//一直左滑动的动画图片@property (nonatomic, strong) UIView *bgView;//顶部的图片@property (nonatomic, strong) UIImageView *topImage;//自定义的刷新提示状态@property (nonatomic, strong) UILabel *customStatusLable;//跑动的ImageV@property (nonatomic, strong) UIImageView *customImageV;//重写父类@property (strong, nonatomic) NSMutableDictionary *stateImages;//重写父类@property (strong, nonatomic) NSMutableDictionary *stateDurations;@end@implementation CustomRefreshGifHeader#pragma mark - 懒加载- (UIImageView *)topImage { if (!_topImage) { [self addSubview:_topImage =[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"顶部图片"]]]; _topImage.frame = CGRectMake(0, -360, WIDTH, 360); _topImage.contentMode = UIViewContentModeScaleAspectFit; } return _topImage;}- (UIView *)bgView { if (!_bgView) { [self addSubview:_bgView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, WIDTH * 2, 60)]]; for (int i = 0; i < 2; i ++) { UIImageView *image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"refreshbg"]]; image.frame = CGRectMake(WIDTH * i, 0, WIDTH, 60); image.contentMode = UIViewContentModeScaleAspectFill; [_bgView addSubview:image]; } } return _bgView;}- (UIImageView *)customImageV { if (!_customImageV ) { [self addSubview:_customImageV = [[UIImageView alloc] init]]; } return _customImageV;}- (NSMutableDictionary *)stateImages { if (!_stateImages) { self.stateImages = [NSMutableDictionary dictionary]; } return _stateImages;}- (NSMutableDictionary *)stateDurations { if (!_stateDurations) { self.stateDurations = [NSMutableDictionary dictionary]; } return _stateDurations;}#pragma mark - 公共方法//重写动画实现- (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state { if (images == nil) return; self.stateImages[@(state)] = images; self.stateDurations[@(state)] = @(duration); /* 根据图片设置控件的高度 */ UIImage *image = [images firstObject]; if (image.size.height > self.mj_h) { self.mj_h = image.size.height; }}- (void)setImages:(NSArray *)images forState:(MJRefreshState)state { [self setImages:images duration:images.count * 0.1 forState:state];}#pragma mark - 实现父类的方法//初始化操作- (void)prepare { [super prepare]; self.labelLeftInset = 20; [self bgView]; [self topImage]; self.lastUpdatedTimeLabel.hidden = YES; self.gifView.hidden = YES; self.stateLabel.hidden = YES; [self bringSubviewToFront:self.customStatusLable]; [self bringSubviewToFront:self.customImageV];}///重写MJ百分比- (void)setPullingPercent:(CGFloat)pullingPercent { [super setPullingPercent:pullingPercent]; //如果拖动的百分比大于1则显示为1 if (self.scrollView.dragging) { if (pullingPercent >= 1) { pullingPercent = 0.9999; } } self.customImageV.frame = CGRectMake(WIDTH * 0.2 * pullingPercent , 60 * (1 - pullingPercent), 60 * pullingPercent, 60 * pullingPercent); if (self.bgView.layer.animationKeys.count == 0) { [self.bgView.layer addAnimation:[self creatAnimation] forKey:@"animation"]; } NSArray *images = self.stateImages[@(MJRefreshStateIdle)]; if (self.state != MJRefreshStateIdle || images.count == 0) return; [self.customImageV stopAnimating]; NSUInteger index = images.count * pullingPercent; if (index >= images.count) index = images.count - 1; self.customImageV.image = images[index]; [self layoutSubviews];}//新的动画图片frame不在根据placeSubviews调整, 而是在拖动百分比中设置- (void)placeSubviews { [super placeSubviews];}- (void)setState:(MJRefreshState)state { MJRefreshCheckState#pragma mark 无论是状态还是百分比发生变化, 均检测一次是否有动画; 若没有,添加 if (self.bgView.layer.animationKeys.count == 0) { [self.bgView.layer addAnimation:[self creatAnimation] forKey:@"animation"]; } //自定义位置的提示刷新状态始终跟父类的保持一致 self.customStatusLable.text = self.stateLabel.text; if (state == MJRefreshStatePulling || state == MJRefreshStateRefreshing) { NSArray *images = self.stateImages[@(state)]; if (images.count == 0) return; [self.customImageV stopAnimating]; if (images.count == 1) { // 单张图片 self.customImageV.image = [images lastObject]; } else { // 多张图片 self.customImageV.animationImages = images; self.customImageV.animationDuration = [self.stateDurations[@(state)] doubleValue]; [self.customImageV startAnimating]; } } else if (state == MJRefreshStateIdle) { [self.customImageV stopAnimating]; }}//主要效果就是实现当刷新状态完成时仍然能够保持动画完成.- (void)endRefreshing { __weak CustomRefreshGifHeader *weakSelf = self; [UIView animateWithDuration:1.3f animations:^{ weakSelf.customImageV.frame = CGRectMake(WIDTH + 10, 60 * 0.00001, 60 * 0.9999, 60 * 0.9999); } completion:^(BOOL finished) { //向右跑动的动画当跑出屏幕后就置位zero weakSelf.customImageV.frame = CGRectZero; dispatch_async(dispatch_get_main_queue(), ^{ weakSelf.state = MJRefreshStateIdle; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf.bgView.layer removeAllAnimations]; }); }); }];}#pragma mark Animation- (CABasicAnimation *)creatAnimation { self.bgView.layer.anchorPoint = CGPointMake(0, 0); CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"]; animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)]; animation.toValue = [NSValue valueWithCGPoint:CGPointMake(-WIDTH, 0)]; animation.repeatCount = MAXFLOAT; animation.duration = 20; animation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionLinear]; animation.removedOnCompletion = NO; animation.fillMode = kCAFillModeBackwards; return animation;}- (UILabel *)customStatusLable { if (!_customStatusLable) { [self addSubview:_customStatusLable = [[UILabel alloc] initWithFrame:CGRectMake(0, 40, WIDTH, 20)]]; _customStatusLable.font = [UIFont systemFontOfSize:10]; _customStatusLable.textAlignment = NSTextAlignmentCenter; _customStatusLable.textColor = [UIColor darkGrayColor]; } return _customStatusLable;}- (void)dealloc { NSLog(@"%@------------dealloc", self.class);}@end
使用时只需将自定义的类拖进工程即可,跟原本MJ使用方法相同.详见demo
Demo地址
0 0
- iOS-自定义MJRefresh下拉刷新动画
- iOS 利用MJRefresh实现上拉刷新下拉加载(自定义动画)
- iOS 利用MJRefresh实现上拉刷新下拉加载(自定义动画)
- MJRefresh实现动画下拉刷新
- iOS 下拉刷新 MJRefresh 详解
- iOS开发---MJRefresh下拉刷新/下拉加载
- iOS 下拉刷新 上拉刷新 MJRefresh
- 基于MJRefresh的自定义下拉刷新
- MJRefresh-- iOS下拉刷新第三方类库
- IOS MJRefresh下拉刷新的使用
- iOS开发- MJRefresh第三方详解(下拉刷新,下拉加载)
- 利用MJRefresh 完成下拉出gif动画刷新
- iOS 上拉加载,下拉刷新,本人使用MJRefresh
- iOS-上拉刷新下拉加载 新版MJRefresh和EGOTableViewPullRefresh
- IOS MJRefresh给tableview下拉刷新上拉加载分页
- PullToRrefresh自定义下拉刷新动画
- PullToRrefresh自定义下拉刷新动画
- PullToRrefresh自定义下拉刷新动画
- PDO 简介——PDO中的三个类及其方法
- UE4 VR 模式下全屏解决办法
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- JavaScript三目运算符
- Spring 4 WebSocket发送到指定用户:convertAndSendToUser函数
- iOS-自定义MJRefresh下拉刷新动画
- 面向对象之内部类
- Apache配置虚拟主机
- shell 管理 uwsgi 进行重启 防止多个进行 导致服务器挂掉
- 如何做好机器人方向的毕业设计?
- 用mm编译APK时大量can't find referenced method的问题的解决
- linux 下安装jdk
- 销项税额
- PowerShell 中通过 Plink 运行 SSH 命令