[翻译] GSProgressView

简介:

GSProgressView

 

本人极不推荐使用drawRect的方式来绘制下载进度条,无论机器的性能怎么高,使用drawRect用于绘制图形都是低效的。

 

A cute little circular progress view for iOS

一款轻巧的显示圆形进度的的view,用于iOS开发

 

Installation - 安装

Drag GSProgressView.h and GSProgressView.m into your project.

将GSProgressView.h与GSProgressView.m拖到你的工程当中。

 

Serving suggestion - 建议的使用方式

GSProgressView *pv = [[GSProgressView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
pv.color = [UIColor redColor];
pv.progress = 0.6;
[myView addSubview:pv];

GSProgressView.h + GSProgressView.m.


//
//  GSProgressView.h
//
//  Created by Simon Whitaker on 14/11/2012.
//  Copyright (c) 2012 Goo Software Ltd. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface GSProgressView : UIView

@property (nonatomic) CGFloat progress;
@property (strong, nonatomic) UIColor *color UI_APPEARANCE_SELECTOR;
@property (strong, nonatomic) UIColor *tickColor UI_APPEARANCE_SELECTOR;

@end


//
//  GSProgressView.m
//
//  Created by Simon Whitaker on 14/11/2012.
//  Copyright (c) 2012 Goo Software Ltd. All rights reserved.
//

#import "GSProgressView.h"
#import <QuartzCore/QuartzCore.h>

@implementation GSProgressView

- (void)commonInit {
    self.backgroundColor = [UIColor clearColor];
}

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self commonInit];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self commonInit];
    }
    return self;
}

- (void)setProgress:(CGFloat)progress {
    if (progress > 1.0) progress = 1.0;
    
    if (progress != _progress) {
        _progress = progress;
        [self setNeedsDisplay];
    }
}

- (void)drawRect:(CGRect)rect {
    if ([self color] == nil)
        [self setColor:[UIColor blackColor]];
    
    CGPoint center = CGPointMake(rect.size.width/2, rect.size.height/2);
    CGFloat radius = MIN(rect.size.width, rect.size.height)/2;
    
    // Start a path
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    // Move to centre and draw an arc.
    
    [path moveToPoint:center];
    [path addArcWithCenter:center
                    radius:radius
                startAngle:0 - M_PI_2 // zero degrees is east, not north, so subtract pi/2
                  endAngle:2 * M_PI * [self progress] - M_PI_2 // ditto
                 clockwise:YES];
    [path closePath];
    
    // If progress is 1.0, show a tick mark in the centre of the circle
    if ([self progress] == 1.0) {
        /* 
         First draw a tick that looks like this:
         
           A---F
           |   |
           |   E-------D
           |           |
           B-----------C
         
         (Remember: (0,0) is top left)
         */
        UIBezierPath *tickPath = [UIBezierPath bezierPath];
        CGFloat tickWidth = radius/3;
        [tickPath moveToPoint:CGPointMake(0, 0)];                            // A
        [tickPath addLineToPoint:CGPointMake(0, tickWidth * 2)];             // B
        [tickPath addLineToPoint:CGPointMake(tickWidth * 3, tickWidth * 2)]; // C
        [tickPath addLineToPoint:CGPointMake(tickWidth * 3, tickWidth)];     // D
        [tickPath addLineToPoint:CGPointMake(tickWidth, tickWidth)];         // E
        [tickPath addLineToPoint:CGPointMake(tickWidth, 0)];                 // F
        [tickPath closePath];
        
        // Now rotate it through -45 degrees...
        [tickPath applyTransform:CGAffineTransformMakeRotation(-M_PI_4)];
        
        // ...and move it into the right place.
        [tickPath applyTransform:CGAffineTransformMakeTranslation(radius * 0.43, radius)];
        
        // Account for non-square views
        CGFloat xOffset = rect.size.width/2 - radius;
        CGFloat yOffset = rect.size.height/2 - radius;
        [tickPath applyTransform:CGAffineTransformMakeTranslation(xOffset, yOffset)];

        // Add fill color if it's set
        if (self.tickColor) {
            [[self tickColor] setFill];
            [tickPath fill];
        }

        // Add the tick path to the existing circle path
        [path appendPath:tickPath];
    };
    path.usesEvenOddFillRule = YES;
    
    [[self color] setFill];
    [path fill];
}

#pragma mark - Accessibility

- (BOOL)isAccessibilityElement {
    return YES;
}

- (NSString *)accessibilityLabel {
    return NSLocalizedString(@"Progress", @"Accessibility label for GSProgressView");
}

- (NSString *)accessibilityValue {
    // Report progress as a percentage, same as UISlider, UIProgressView
    return [NSString stringWithFormat:@"%d%%", (int)round([self progress] * 100.0)];
}

- (UIAccessibilityTraits)accessibilityTraits {
    return UIAccessibilityTraitUpdatesFrequently;
}

@end



目录
相关文章
|
存储 自然语言处理 前端开发
从零写一个Recoil(翻译)
Rewriting Recoil from scratchrecoil是facebook编写的一个库,它之所以诞生是因为人体工程学、context的性能问题和useState。这是一个非常聪明的库,几乎每个人都会找到它的用途——如果你想了解更多,请查看这段解释视频。刚开始我被图论和recoil惊到了,但渐渐的理解后,感觉也没那么特别了。也许我也可以实现一个类似的东西。我自己实现的版本和recoil
198 0
从零写一个Recoil(翻译)
|
XML Java Android开发
[翻译]IAdaptable是什么?
IAdaptable在Eclipse里是一个非常重要的接口。对于Eclipse开发老手来说,它就像异常处理和抽象类一样寻常;但是对新手而言,它却令人感到困惑和畏惧。这篇文章将向你解释IAdaptable到底是什么,以及它在Eclipse里起到的作用。
1178 0
|
Java iOS开发
|
开发工具 iOS开发 MacOS
|
iOS开发 Perl
|
Apache iOS开发 Perl
|
iOS开发 Perl