【原】Github系列之三:開源iOS下 漸變顏色的進度條WGradientProgress

概述

今天咱們來實現一個iOS平臺上的進度條(progress bar or progress view)。這種進度條比APPLE自帶的更加漂亮,更加有「B格」。它擁有漸變的顏色,並且這種顏色是動態移動的,這裏稱之爲WGradientProgress。git

先來看看咱們的目標長什麼樣子:github

   

 

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的頂部

 

主要的接口有如下幾個:ide

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

  


 

分析

 

這裏咱們看一下,實現出這樣的效果須要解決哪些技術難點:oop

  • 如何實現一個靜態的具備漸變顏色的色帶
  • 如何實現色帶顏色循環移動
  • 如何關聯進度值與色帶的寬度

 

(1)如何實現一個靜態的具備漸變顏色的色帶

這裏須要使用CALayer的子類CAGradientLayer。CAGradientLayer用於實現顏色漸變,關於CAGradietnLayer的介紹請看這裏。咱們使用到的屬性有startPoint、endPoint、colors。spa

咱們能夠這樣子作出一個靜態的漸變色帶,你也能夠修改colors數組來實現不一樣顏色的色帶:.net

 

    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數組的最後一個顏色值插到數組開始處。定時器的執行代碼以下:blog

 

/**
 *  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/機器視覺等領域展開交流!

相關文章
相關標籤/搜索