概述

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

主要的接口有以下几个:

+ (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数组来实现不同颜色的色带:

    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 section
NSMutableArray *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数组的最后一个颜色值插到数组开始处。定时器的执行代码如下:

/**
* 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的启动、暂停、永远停止这三个操作要分清,尤其是暂停与停止:

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

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

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

CALayer *layer = new
layer.mask = _maskLayer;
layer.visualSection = _maskLayer.bounds;

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

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

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

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

- (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


原创文章,转载请注明 编程小翁@博客园,邮件zilin_weng@163.com,欢迎各位与我在C/C++/Objective-C/机器视觉等领域展开交流!


【原】Github系列之三:开源iOS下 渐变颜色的进度条WGradientProgress的更多相关文章

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

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

  2. .Neter玩转Linux系列之三:Linux下的分区讲解

    基础篇 .Neter玩转Linux系列之一:初识Linux .Neter玩转Linux系列之二:Linux下的文件目录及文件目录的权限 .Neter玩转Linux系列之三:Linux下的分区讲解 .N ...

  3. 纯css使用线性渐变实现滚动进度条(来自于微信前端早读课)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. 【iOS实现一个颜色渐变的弧形进度条】

    在Github上看到一些进度条的功能,都是通过Core Graph来实现.无所谓正确与否,但是开发效率明显就差很多了,而且运行效率还是值得考究的.其实使用苹果提供的Core Animation能够非常 ...

  5. iOS实现渐变颜色

    下面是我的两种实现: 1.直接图片展示,注意图片的变形问题; 2.用CAGradientLayer渐变颜色实现; 代码如下: // // ViewController.m // ImageStrenc ...

  6. windows下flv视频网站进度条随意拖放[转]

    网站中视频都转换成flv格式,奈何flv格式无法拖拽,此问题纠结了好久,最终得以解决.现将解决思路记录下来,大多数源于网上找到的. 视频拖拽满足要求 1.播放器要支持 2.flv视频要有关键帧和met ...

  7. iOS 开发技巧-制作环形进度条

    有几篇博客写到了怎么实现环形进度条,大多是使用Core Graph来实现,实现比较麻烦且效率略低,只是一个小小的进度条而已,我们当然是用最简单而且效率高的方式来实现. 先看一下这篇博客,博客地址:ht ...

  8. iOS一分钟学会环形进度条

    有几篇博客写到了怎么实现环形进度条,大多是使用Core Graph来实现,实现比较麻烦且效率略低,只是一个小小的进度条而已,我们当然是用最简单而且效率高的方式来实现.先看一下这篇博客,博客地址:htt ...

  9. MediaPlayer音乐播放器、上一首、下一首、播放、停止、自动下一首、进度条

    本文介绍MediaPlayer的使用.MediaPlayer可以播放音频和视频,另外也可以通过VideoView来播放视频,虽然VideoView比MediaPlayer简单易用,但定制性不如用Med ...

随机推荐

  1. ABZ理论

    前言 身为著名的创业者+投资人,LinkedIn和Paypal的联合创始人Reid Hoffman有一个令我印象深刻的ABZ理论,他认为,你在任何时刻,手中都需要有三个计划:A计划.B计划和Z计划. ...

  2. Windows Live Writer 的昨日荣光

    今天这一篇文章,想写一写Windows Live Writer这款博客编辑器(最早的一个版本是2007年发布的).毫不夸张地说,这是为数不多的几款所见即所得的编辑器之一,当然,它的运行速度慢也是一个众 ...

  3. 利用private font改变PDF文件的字体

    利用private font改变PDF文件的字体 前几天做项目,需要使用未安装的字体来改变PDF的文件.以前并没有实现过类似的功能,幸运的是我在网上找到了类似的教程,并成功实现了这个功能. 下面就跟大 ...

  4. Callbacks vs Events

    前言:本文翻译自Dean Edwards的一篇文章,原文地址:http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/. 文章主要指出了 ...

  5. 在Linux下的中断方式读取按键驱动程序

    // 在Linux下的中断方式读取按键驱动程序 //包含外部中断 休眠 加入poll机制 // 采用异步通知的方式 // 驱动程序发 ---> app接收 (通过kill_fasync()发送) ...

  6. Fragment基础----生命周期

    Fragment生命周期和Activity对比 注意:在一个app的运行期间,前台的activity有时可能会被其他的视图组件打断,然后进入pause状态. 比如打开一个半透膜的activity (比 ...

  7. CSS魔法堂:重拾Border之——不仅仅是圆角

    前言  当CSS3推出border-radius属性时我们是那么欣喜若狂啊,一想到终于不用再添加额外元素来模拟圆角了,但发现border-radius还分水平半径和垂直半径,然后又发现border-t ...

  8. WebView JS与RN进行通讯

    RN0.37终于官方增加了WebView与React Native的通讯,之前一真使用的是第三方控件React-Native-WebView-Bridge,但不是知道怎么回事这个第三方控件喊了很长时间 ...

  9. 【MVVM Light】新手初识MVVM,你一看就会

    一.前言 作为一个初入软件业的新手,各种设计模式与框架对我是眼花缭乱的.所以当我接触到这些新知识的时候就希望自己能总结几个步骤,以便更好更方便的在日常工作中进行使用. MVVM顾名思义就是Model- ...

  10. Extjs.FormPanel

    刚刚学习ExtJS ,备注一哈代码 防止忘记... <html xmlns="http://www.w3.org/1999/xhtml"> <head runat ...