Welcome

首页 / 移动开发 / IOS / IOS使用progssview仿滴滴打车圆形计时

实现类似在微信中使用的滴滴打车的progressview,实现效果如图


//// CCProgressView.h// HurricaneConsumer//// Created by wangcong on 15-3-25.// Copyright (c) 2015年 WangCong. All rights reserved.// #import <UIKit/UIKit.h>#import <QuartzCore/QuartzCore.h> /** * 动画开始 */typedef void(^block_progress_start)(); /** * 动画正在进行 * @param NSTimeInterval */typedef void(^block_progress_animing)(NSTimeInterval); /** * 动画结束 */typedef void(^block_progress_stop)(); @interface CCProgressView : UIView{NSTimeInterval _animationTime;} @property (nonatomic, strong) UILabel *centerLabel;// 中心Label @property (nonatomic, copy) block_progress_start start; // 动画开始回调@property (nonatomic, copy) block_progress_animing animing; // 动画进行@property (nonatomic, copy) block_progress_stop stop;// 动画结束回调 - (void) setAnimationTime:(NSTimeInterval)animationTime; - (void)startAnimation; - (void)stopAnimation; @end//// CCProgressView.m// HurricaneConsumer//// Created by wangcong on 15-3-25.// Copyright (c) 2015年 WangCong. All rights reserved.// #import "CCProgressView.h" #define kProgressThumbWh 30 // 计时器间隔时长#define kAnimTimeInterval 0.1 /** * 圆圈layer上旋转的layer */@interface CCProgressThumb : CALayer{NSTimeInterval _animationTime;} @property (assign, nonatomic) double startAngle;@property (nonatomic, strong) UILabel *timeLabel;// 显示时间Label @end @implementation CCProgressThumb - (instancetype)init{if ((self = [super init])) {[self setupLayer];}return self;} - (void)layoutSublayers{_timeLabel.frame = self.bounds; [_timeLabel sizeToFit];_timeLabel.center = CGPointMake(CGRectGetMidX(self.bounds) - _timeLabel.frame.origin.x,CGRectGetMidY(self.bounds) - _timeLabel.frame.origin.y);} - (void)setupLayer{// 绘制圆UIGraphicsBeginImageContext(CGSizeMake(kProgressThumbWh, kProgressThumbWh));CGContextRef ctx = UIGraphicsGetCurrentContext();CGContextSetLineWidth(ctx, 1);CGContextSetFillColorWithColor(ctx, [UIColor lightGrayColor].CGColor);CGContextSetStrokeColorWithColor(ctx, [UIColor lightGrayColor].CGColor);CGContextAddEllipseInRect(ctx, CGRectMake(1, 1, kProgressThumbWh - 2, kProgressThumbWh - 2));CGContextDrawPath(ctx, kCGPathFillStroke);UIImage *circle = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext(); UIImageView *circleView = [[UIImageView alloc] initWithImage:circle];circleView.frame = CGRectMake(0, 0, kProgressThumbWh, kProgressThumbWh);circleView.image = circle;[self addSublayer:circleView.layer]; _timeLabel = [[UILabel alloc] initWithFrame:self.bounds];_timeLabel.textColor = [UIColor redColor];_timeLabel.font = [UIFont systemFontOfSize:10];_timeLabel.textAlignment = NSTextAlignmentCenter;_timeLabel.text = @"00:00";[self addSublayer:_timeLabel.layer]; _startAngle = - M_PI / 2;} - (void)setAnimationTime:(NSTimeInterval)animationTime{_animationTime = animationTime;} - (double)calculatePercent:(NSTimeInterval)fromTime toTime:(NSTimeInterval)toTime{double progress = 0.0f;if ((toTime > 0) && (fromTime > 0)) {progress = fromTime / toTime;if ((progress * 100) > 100) {progress = 1.0f;}}return progress;} - (void)startAnimation{CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];pathAnimation.calculationMode = kCAAnimationPaced;pathAnimation.fillMode = kCAFillModeForwards;pathAnimation.removedOnCompletion = YES;pathAnimation.duration = kAnimTimeInterval;pathAnimation.repeatCount = 0;pathAnimation.autoreverses = YES; CGMutablePathRef arcPath = CGPathCreateMutable();CGPathAddPath(arcPath, NULL, [self bezierPathFromParentLayerArcCenter]);pathAnimation.path = arcPath;CGPathRelease(arcPath);[self addAnimation:pathAnimation forKey:@"position"];} /** * 根据父Layer获取到一个移动路径 * @return */- (CGPathRef)bezierPathFromParentLayerArcCenter{CGFloat centerX = CGRectGetWidth(self.superlayer.frame) / 2.0;CGFloat centerY = CGRectGetHeight(self.superlayer.frame) / 2.0;double tmpStartAngle = _startAngle;_startAngle = _startAngle + (2 * M_PI) * kAnimTimeInterval / _animateTime;return [UIBezierPath bezierPathWithArcCenter:CGPointMake(centerX, centerY) radius:centerX startAngle:tmpStartAngleendAngle:_startAngleclockwise:YES].CGPath;} - (void)stopAnimation{[self removeAllAnimations];} - (void)dealloc{[[NSNotificationCenter defaultCenter] removeObserver:self];} @end /** * 圆圈layer */@interface CCProgress : CAShapeLayer{NSTimeInterval _animationTime;} @property (assign, nonatomic) double initialProgress;@property (nonatomic) NSTimeInterval elapsedTime; //已使用时间@property (assign, nonatomic) double percent;@property (nonatomic, strong) UIColor *circleColor;@property (nonatomic, strong) CAShapeLayer *progress;@property (nonatomic, strong) CCProgressThumb *thumb;@property (nonatomic, assign) CGRect frame; @end @implementation CCProgress - (instancetype) init{if ((self = [super init])) {[self setupLayer];}return self;} - (void)layoutSublayers{self.path = [self bezierPathWithArcCenter];self.progress.path = self.path; self.thumb.frame = CGRectMake((320 - kProgressThumbWh) / 2.0f, 180, kProgressThumbWh, kProgressThumbWh);[super layoutSublayers];} - (void)setupLayer{// 绘制圆self.path = [self bezierPathWithArcCenter];self.fillColor = [UIColor clearColor].CGColor;self.strokeColor = [UIColor colorWithRed:0.86f green:0.86f blue:0.86f alpha:0.4f].CGColor;self.lineWidth = 2; // 添加可以变动的滚动条self.progress = [CAShapeLayer layer];self.progress.path = self.path;self.progress.fillColor = [UIColor clearColor].CGColor;self.progress.strokeColor = [UIColor whiteColor].CGColor;self.progress.lineWidth = 4;self.progress.lineCap = kCALineCapSquare;self.progress.lineJoin = kCALineCapSquare;[self addSublayer:self.progress]; // 添加可以旋转的ThumbLayerself.thumb = [[CCProgressThumb alloc] init];[self addSublayer:self.thumb];} /** * 得到bezier曲线路劲 * @return */- (CGPathRef)bezierPathWithArcCenter{CGFloat centerX = CGRectGetWidth(self.frame) / 2.0;CGFloat centerY = CGRectGetHeight(self.frame) / 2.0;return [UIBezierPath bezierPathWithArcCenter:CGPointMake(centerX, centerY) radius:centerX startAngle:(- M_PI / 2)endAngle:(3 * M_PI / 2)clockwise:YES].CGPath;} - (void)setCircleColor:(UIColor *)circleColor{self.progress.strokeColor = circleColor.CGColor;} - (void)setAnimtionTime:(NSTimeInterval)animtionTime{_animationTime = animtionTime;[self.thumb setAnimationTime:animtionTime];} - (void)setElapsedTime:(NSTimeInterval)elapsedTime{_initialProgress = [self calculatePercent:_elapsedTime toTime:_animationTime];_elapsedTime = elapsedTime; self.progress.strokeEnd = self.percent;[self startAnimation];} - (double)percent{_percent = [self calculatePercent:_elapsedTime toTime:_animationTime];return _percent;} - (double)calculatePercent:(NSTimeInterval)fromTime toTime:(NSTimeInterval)toTime{double progress = 0.0f;if ((toTime > 0) && (fromTime > 0)) {progress = fromTime / toTime;if ((progress * 100) > 100) {progress = 1.0f;}}return progress;} - (void)startAnimation{CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];pathAnimation.duration = kAnimTimeInterval;pathAnimation.fromValue = @(self.initialProgress);pathAnimation.toValue = @(self.percent);pathAnimation.removedOnCompletion = YES;[self.progress addAnimation:pathAnimation forKey:nil]; [self.thumb startAnimation];self.thumb.timeLabel.text = [self stringFromTimeInterval:_elapsedTime shorTime:YES];} - (void)stopAnimation{_elapsedTime = 0;self.progress.strokeEnd = 0.0;[self removeAllAnimations];[self.thumb stopAnimation];} /** * 时间格式转换 * @param interval NSTimeInterval * @param shortTime BOOL * @return */- (NSString *)stringFromTimeInterval:(NSTimeInterval)interval shorTime:(BOOL)shortTime{NSInteger ti = (NSInteger)interval;NSInteger seconds = ti % 60;NSInteger minutes = (ti / 60) % 60;NSInteger hours = (ti / 3600);if (shortTime) {return [NSString stringWithFormat:@"%02ld:%02ld", (long)hours, (long)seconds];} else {return [NSString stringWithFormat:@"%02ld:%02ld:%02ld", (long)hours, (long)minutes, (long)seconds];}} @end @interface CCProgressView () @property (nonatomic, strong) CCProgress *progressLayer;@property (nonatomic, strong) NSTimer *timer; @end @implementation CCProgressView - (instancetype)init{if ((self = [super init])) {[self setupView];}return self;} - (instancetype)initWithFrame:(CGRect)frame{if ((self = [super initWithFrame:frame])) {[self setupView];}return self;} - (void)layoutSubviews{[super layoutSubviews];self.progressLayer.frame = self.bounds; [self.centerLabel sizeToFit];self.centerLabel.center = CGPointMake(self.center.x - self.frame.origin.x, self.center.y- self.frame.origin.y);} - (void)setupView{self.backgroundColor = [UIColor clearColor];self.clipsToBounds = false; self.progressLayer = [[CCProgress alloc] init];self.progressLayer.frame = self.bounds;[self.layer addSublayer:self.progressLayer]; _centerLabel = [[UILabel alloc] initWithFrame:self.bounds];_centerLabel.font = [UIFont systemFontOfSize:18];_centerLabel.textAlignment = NSTextAlignmentCenter;_centerLabel.textColor = [UIColor whiteColor];_centerLabel.text = @"已推送至 3 家";[self.layer addSublayer:_centerLabel.layer];} - (void)setAnimationTime:(NSTimeInterval)animationTime{_animationTime = animationTime;[self.progressLayer setAnimtionTime:animationTime];} - (void)startAnimation{if (!_timer) {_timer = [NSTimer timerWithTimeInterval:kAnimTimeInterval target:self selector:@selector(doTimerSchedule) userInfo:nil repeats:YES];[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];}self.progressLayer.elapsedTime = 0;if (_start) _start();} - (void)doTimerSchedule{self.progressLayer.elapsedTime = self.progressLayer.elapsedTime + kAnimTimeInterval;;if (_animing) _animing(self.progressLayer.elapsedTime); if (self.progressLayer.elapsedTime >= _animationTime) {[self stopAnimation];}} - (void)stopAnimation{if (_stop) _stop();if (_timer) {[_timer invalidate];_timer = nil;}[_progressLayer stopAnimation];} @end 使用实例_progressView = [[CCProgressView alloc] initWithFrame:CGRectMake((APP_WIDTH - 240) / 2.0f, (APP_HEIGHT - 240) / 2.0f, 240, 240)];[_progressView setAnimationTime:60];_progressView.start = ^() {NSLog(@"开始");};_progressView.animing = ^ (NSTimeInterval currentTime) {NSLog(@"进行中");};__block id weakSelf = self;_progressView.stop = ^ () {NSLog(@"结束");[weakSelf dismiss];};[self addSubview:_progressView]; [_progressView startAnimation];
以上所述就是本文的全部内容了,希望大家能够喜欢