欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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]; 

实现:

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

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

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

上一篇:

下一篇: