当前位置: 移动技术网 > 移动技术>移动开发>IOS > iOS实现带动画的环形进度条

iOS实现带动画的环形进度条

2019年07月24日  | 移动技术网移动技术  | 我要评论

本篇写的是实现环形进度条,并带动画效果,要实现这些,仅能通过自己画一个

方法直接看代码

为了方便多次调用,用继承uiview的方式

.m文件

#import <uikit/uikit.h>

@interface loopprogressview : uiview

@property (nonatomic, assign) cgfloat progress;


@end

.h文件

nstimer的调用并非精确,可以自行百度

 这里因为每0.01s启动一次定时器,所以要同步进度条和数字,就将self.progress赋值给动画的duration属性就可以了,duration为动画时间。

 在使用时我发现如果在tableviewcell中添加了这个环形进度条时有个缺点,就是定时器原本用的是系统的runloop,导致数据显示滞后,所以现更新为子线程里添加定时器,子线程的定时器必须添加[[nsrunloop currentrunloop] run];才可启动定时器,因为子线程的runloop里是不带nstimer的,要手动添加运行。

#import "loopprogressview.h"
#import <quartzcore/quartzcore.h>

#define viewwidth self.frame.size.width //环形进度条的视图宽度
#define progresswidth 2.5   //环形进度条的圆环宽度
#define radius viewwidth/2-progresswidth //环形进度条的半径

@interface loopprogressview()
{
 cashapelayer *arclayer;
 uilabel *label;
 nstimer *progresstimer;
}
@property (nonatomic,assign)cgfloat i;

@end

@implementation loopprogressview

-(id)initwithframe:(cgrect)frame
{
 self = [super initwithframe:frame];
 if (self) {
 self.backgroundcolor = [uicolor clearcolor];
 }
 return self;
}

-(void)drawrect:(cgrect)rect
{
 _i=0;
 cgcontextref progresscontext = uigraphicsgetcurrentcontext();
 cgcontextsetlinewidth(progresscontext, progresswidth);
 cgcontextsetrgbstrokecolor(progresscontext, 209.0/255.0, 209.0/255.0, 209.0/255.0, 1);
 
 cgfloat xcenter = rect.size.width * 0.5;
 cgfloat ycenter = rect.size.height * 0.5;
 
 //绘制环形进度条底框
 cgcontextaddarc(progresscontext, xcenter, ycenter, radius, 0, 2*m_pi, 0);
 cgcontextdrawpath(progresscontext, kcgpathstroke);
 
 // //绘制环形进度环
 cgfloat to = self.progress * m_pi * 2; // - m_pi * 0.5为改变初始位置
 
 // 进度数字字号,可自己根据自己需要,从视图大小去适配字体字号
 int fontnum = viewwidth/6;
 49 label = [[uilabel alloc]initwithframe:cgrectmake(0, 0,radius+10, viewwidth/6)];
 label.center = cgpointmake(xcenter, ycenter);
 label.textalignment = nstextalignmentcenter;
 label.font = [uifont boldsystemfontofsize:fontnum];
 label.text = @"0%";
 [self addsubview:label];
 
 uibezierpath *path=[uibezierpath bezierpath];
 [path addarcwithcenter:cgpointmake(xcenter,ycenter) radius:radius startangle:0 endangle:to clockwise:yes];
 arclayer=[cashapelayer layer];
 arclayer.path=path.cgpath;//46,169,230
 arclayer.fillcolor = [uicolor clearcolor].cgcolor;
 arclayer.strokecolor=[uicolor colorwithred:227.0/255.0 green:91.0/255.0 blue:90.0/255.0 alpha:0.7].cgcolor;
 arclayer.linewidth=progresswidth;
 arclayer.backgroundcolor = [uicolor bluecolor].cgcolor;
 [self.layer addsublayer:arclayer];
 
 
 dispatch_async(dispatch_get_global_queue(0, 0), ^{
 [self drawlineanimation:arclayer];
 });
 
 if (self.progress > 1) {
 nslog(@"传入数值范围为 0-1");
 self.progress = 1;
 }else if (self.progress < 0){
 nslog(@"传入数值范围为 0-1");
 self.progress = 0;
 return;
 }
 
 if (self.progress > 0) {
 nsthread *thread = [[nsthread alloc]initwithtarget:self selector:@selector(newthread) object:nil];
 [thread start];
 }
 
}

-(void)newthread
{
 @autoreleasepool {
 progresstimer = [nstimer scheduledtimerwithtimeinterval:0.01 target:self selector:@selector(timelabel) userinfo:nil repeats:yes];
 [[nsrunloop currentrunloop] run];
 }
}

//nstimer不会精准调用
-(void)timelabel
{
 _i += 0.01;
 label.text = [nsstring stringwithformat:@"%.0f%%",_i*100];
 
 if (_i >= self.progress) {
 [progresstimer invalidate];
 progresstimer = nil;
 
 }
 
}

//定义动画过程
-(void)drawlineanimation:(calayer*)layer
{
 cabasicanimation *bas=[cabasicanimation animationwithkeypath:@"strokeend"];
 bas.duration=self.progress;//动画时间
 bas.delegate=self;
 bas.fromvalue=[nsnumber numberwithinteger:0];
 bas.tovalue=[nsnumber numberwithinteger:1];
 [layer addanimation:bas forkey:@"key"];
}
@end
 

完成后在要调用的控制器里,仅需几段代码:传进的参数:为0-1

 loopprogressview *custom = [[loopprogressview alloc]initwithframe:cgrectmake(50, 100, 100, 100)];
 custom.progress = 0.44;
 [self.view addsubview:custom]; 

实现:

已经实现进度条和数字的同步:


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网