iOS实现带动画的环形进度条
程序员文章站
2023-12-21 13:40:46
本篇写的是实现环形进度条,并带动画效果,要实现这些,仅能通过自己画一个
方法直接看代码
为了方便多次调用,用继承uiview的方式
.m文件
#import...
本篇写的是实现环形进度条,并带动画效果,要实现这些,仅能通过自己画一个
方法直接看代码
为了方便多次调用,用继承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];
实现:
已经实现进度条和数字的同步:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。