首页 技术 正文
技术 2022年11月10日
0 收藏 637 点赞 3,181 浏览 4271 个字

今天我们来实现一个iOS平台上的进度条(progress bar or progress view)。这种进度条比APPLE自带的更加漂亮,更加有“B格”。它拥有渐变的颜色,而且这种颜色是动态移动的,这里称之为WGradientProgress。

先来看看我们的目标长什么样子:

渐变颜色的进度条WGradientProgress-备用

WGradientProgress的使用方法很简单,主要有展示接口以及隐藏接口,目前显示的位置有两种选择:

  • WProgressPosDown        //progress is on the down border of parent view,显示在parent view的底部(主流做法,默认)

  • WProgressPosUp           //progress is on the up border of parent view,也就是显示在parent view的顶部

主要的接口有以下几个:

123456789101112131415161718192021 + (WGradientProgress *)sharedInstance; /** *  the main interface to show WGradientProgress obj, position is WProgressPosDown by default. * *  @param parentView which view to be attach */- (void)showOnParent:(UIView *)parentView; /** *  the main interface to show WGradientProgress obj * *  @param parentView which view to be attach *  @param pos        up or down */- (void)showOnParent:(UIView *)parentView position:(WProgressPos)pos; /** *  the main interface to hide WGradientProgress obj */- (void)hide;

  


分析

这里我们看一下,实现出这样的效果需要解决哪些技术难点:

  • 如何实现一个静态的具有渐变颜色的色带
  • 如何实现色带颜色循环移动
  • 如何关联进度值与色带的宽度

(1)如何实现一个静态的具有渐变颜色的色带

这里需要使用CALayer的子类CAGradientLayer。CAGradientLayer用于实现颜色渐变,关于CAGradietnLayer的介绍请看这里。我们使用到的属性有startPoint、endPoint、colors。

我们可以这样子做出一个静态的渐变色带,你也可以修改colors数组来实现不同颜色的色带:

12345678910111213141516171819 if (self.gradLayer == nil) {    self.gradLayer = [CAGradientLayer layer];    self.gradLayer.frame = self.bounds;//尺寸要与view的layer一致}self.gradLayer.startPoint = CGPointMake(0, 0.5);self.gradLayer.endPoint = CGPointMake(1, 0.5); //create colors, important sectionNSMutableArray *colors = [NSMutableArray array];for (NSInteger deg = 0; deg <= 360; deg += 5) {         UIColor *color;    color = [UIColor colorWithHue:1.0 * deg / 360.0                       saturation:1.0                       brightness:1.0                            alpha:1.0];    [colors addObject:(id)[color CGColor]];}[self.gradLayer setColors:[NSArray arrayWithArray:colors]];

(2)如何实现色带颜色循环移动

色带颜色循环向前移动,本质上是渐变图层gradientLayer的colors数组循环变化。如果理解了这点,那就很容易往下做了。我的做法是使用定时器NSTimer,让定时器的执行方法去循环地改变color数组。另外,既然要做到循环,那么应该循环地取colors数组的最后一个颜色值插到数组开始处。定时器的执行代码如下:

12345678910111213141516171819202122232425262728 /** *  here I use timer to circularly move colors */- (void)setupTimer{    CGFloat interval = 0.03;    if (self.timer == nil) {         self.timer = [NSTimer timerWithTimeInterval:interval target:self                                            selector:@selector(timerFunc)                                            userInfo:nil repeats:YES];    }    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];} /** *  rearrange color array */- (void)timerFunc{    CAGradientLayer *gradLayer = self.gradLayer;    NSMutableArray *copyArray = [NSMutableArray arrayWithArray:[gradLayer colors]];    UIColor *lastColor = [copyArray lastObject];    [copyArray removeLastObject];    if (lastColor) {        [copyArray insertObject:lastColor atIndex:0];    }    [self.gradLayer setColors:copyArray];}

  


*强势插入:

  NSTimer的启动、暂停、永远停止这三个操作要分清,尤其是暂停与停止:

  • 启动:  
123456 - (void)startTimer{    //start timer    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];    [self.timer setFireDate:[NSDate date]];}
  • 暂停:
12345678 /** *  here we just pause timer, rather than stopping forever. *  NOTE: [timer invalidate] is not fit here. */- (void)pauseTimer{    [self.timer setFireDate:[NSDate distantFuture]];}
  • 停止(无法再启动):
1 [self.timer invalidate]

(3)如何关联进度值与色带的宽度

这个问题看起来很简单,但实际上隐藏着一个很好用的技术:mask。mask也称为蒙版,当我们给一个layer设置了mask layer后,layer就只显示出mask layer所覆盖到的区域,其他区域不显示。用伪代码可以描述为:

123 CALayer *layer = newlayer.mask = _maskLayer;layer.visualSection = _maskLayer.bounds;

因此,我们可以将在一开始时就上文的渐变图层gradientLayer大小设置为与view同尺寸,然后通过mask layer设置可见区域。这样,进度条进度值设置问题就转化为mask layer的宽度问题了。

首先,我们添加一个mask layer到gradient layer上:

1234567 self.mask = [CALayer layer];[self.mask setFrame:CGRectMake(self.gradLayer.frame.origin.x, self.gradLayer.frame.origin.y,                               self.progress * self.width, self.height)];self.mask.borderColor = [[UIColor blueColor] CGColor];self.mask.borderWidth = 2;[self.gradLayer setMask:self.mask];[self.layer addSublayer:self.gradLayer];

然后相应进度值的改变如下:

123456789101112 - (void)setProgress:(CGFloat)progress{    if (progress < 0) {        progress = 0;    }    if (progress > 1) {        progress = 1;    }    _progress = progress;    CGFloat maskWidth = progress * self.width;    self.mask.frame = CGRectMake(0, 0, maskWidth, self.height);}

以上就是WGradientProgress的主要技术要点,更具体的细节以及使用方法请下载我github上的代码查看,下载时别忘记随手点个Star,给我更多支持与鼓励!

源代码下载:点我。https://github.com/weng1250/WGradientProgressDemo.git

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,078
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,553
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,402
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,177
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,814
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,898