目录

    前言

    设计

    编码

    PaintCode

前言

自从人生第一篇博客《iOS中的预编译指令的初步探究》问世以来 浏览量竟然达到了360多,(路过的大神勿笑!)这些浏览量使我兴奋异常但又令我黯然神伤,为何我会眼里常含泪水?因为国人伸手党达90%!!!区区只有可怜的三个评论,可怜的三个评论~ 没有鼓励~ 没有鲜花~ 也没有谩骂~ 但是我不哭 因为贱人会笑!我深信:

一日伸手党,bug终身随!

好久没打篮球了,“教练,我想打篮球”。

这次的东西标题为《无比迅速敏捷地开发iOS超精美控件》!就问你怕不怕!!本人深恶痛绝标题党丫的,所以今天我就绝对会展示一些奇淫巧技!帅气并且超快的撸出一个iOS精美控件!别说我坑你?

上图1

这个我叫它DDClock,所有view都使用Quartz 2D绘制,创建后自动与当前系统对时同步,漂亮、精致、优雅…… (如果你看到这里,你说不漂亮、不精致、不优雅,那么请你出去,我担心我会下手过重,呵呵),想知道怎么弄得?别急!让博主带你手拿菜刀砍电线,一路火光加闪电!!!

设计

在工程界有一个说法:

设计的优秀与否,是导致这个产品成败的关键。

好吧设计先行!想好了再动手!想好了再动手在生活中是很重要,比如小学生和初中生是怎么区分的?区别就是在LOL中他们对技能的施放是否进行周密的思考,所以一些选手一个人直接冲进人堆里,技能啪啪一甩,然后就挂了——小学生!所以嘛,做事情前养成思考的习惯,是脱离小学生群体的重要手段哦~

前面说到一点,DDClock创建后需要自动与当前系统对时同步;所以

1、我们不妨让DDClock继承UIView,然后重载


-(void)drawRect:(CGRect)rect

方法,在这个方法中帅气的画出那个时钟所有细节!我们的决心是坚决不使用人民的一张图片!;

2、然后分析整个DDClock只有指针(时分秒针)和指示上下午的AM、PM会动!所以我们要把这些个东西射成变量!关于指针的运动,我们可以使用定时器,每秒都和系统对时;

3、我们还要支持主题的切换,那就给DDClock定义一个枚举咯;

4、然后就这样

5、然后就这样这样

……

哈~ 在我们精细的设计中,这个DDClock的产品形态竟然出乎的饱满,俗话说的好,打铁要趁热,豆腐趁热吃。我们马上祭出杀器XCode!!我知道你现在已经兴奋了

编码

我们就新建一个项目 叫做DDClockDemo吧,用来测试待会我们设计的DDClock。

然后我们就在项目中新建一个Group(文件夹)吧 ,就命名成DDClock嘛~

再然后嘛,我们就在DDClock的文件夹下新建一个OC对象吧(Cocoa Touch Class)取名字DDClock,让它继承UIView

Nice!!来看看我们的工程目录结构 图2

好!我们要开始写代码咯

DDClock.h



//
// DDClock.h
// Created by David on 15/1/26.
// 博客:http://www.cnblogs.com/daiweilai/
// github:https://github.com/daiweilai/
// Copyright (c) 2015年 DavidDay. All rights reserved.
// #import <UIKit/UIKit.h>
#define DDClockSize 200 //默认时钟的长宽都为200
#if ! __has_feature(objc_arc)
#error "需要开启ARC"
#endif @protocol DDLockDelegate @optional
-(UIColor*)rimColor;
-(UIColor*)markColor;
-(UIColor*)faceColor;
-(UIColor*)fontColor;
-(UIColor*)secondHandColor;
-(UIColor*)hourAndMinuteHandColor; @end @interface DDClock : UIView @property (weak, nonatomic) id delegate; typedef NS_ENUM(NSUInteger, DDClockTheme) { //弄一个枚举类型用来更改主题
DDClockThemeDefault = 0,
DDClockThemeDark,
DDClockThemeModerm
}; //DDClock的构造方法 delegate:代理
-(instancetype)initWithDelegate:(id)delegate frame:(CGRect)frame;
///DDClock的构造方法 theme:主题
-(instancetype)initWithTheme:(DDClockTheme)theme frame:(CGRect)frame; @end

DDClock.m



//
// DDClock.h
// Created by David on 15/1/26.
// 博客:http://www.cnblogs.com/daiweilai/
// github:https://github.com/daiweilai/
// Copyright (c) 2015年 DavidDay. All rights reserved.
// #import "DDClock.h" @interface DDClock(){
//// 声明颜色
UIColor* rimColor;
UIColor* faceColor;
UIColor* markColor;
UIColor* secondHandColor;
UIColor* fontColor;
UIColor* hourAndMinuteHandColor;
DDClockTheme _theme;
float _scale;
CGPoint _centerPoint;
}
@end @implementation DDClock -(instancetype)initWithDelegate:(id)delegate frame:(CGRect)frame{
//防止用户在构建的时候传入的height和widt不一样 因为时钟是圆的所以强制把他们变成长宽一样
CGFloat size = frame.size.height>frame.size.width?frame.size.height:frame.size.width;
CGRect realRect = CGRectMake(frame.origin.x, frame.origin.y, size, size);
self = [self initWithFrame:realRect];
if (self) {
_scale = realRect.size.height / DDClockSize; //放大缩小的比例系数
_centerPoint = CGPointMake(size/2, size/2); //中心点
//先使用默认的颜色初始化 防止用户没有调用delegate方法
rimColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1];
faceColor = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 1];
markColor = [UIColor colorWithRed: 160.0/255.0 green: 160.0/255.0 blue: 160.0/255.0 alpha: 1];
secondHandColor = [UIColor colorWithRed: 86.0/255.0 green: 232.0/255.0 blue: 157.0/255.0 alpha: 1];
fontColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1];
hourAndMinuteHandColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1]; //判断用户是否使用了delegate的方法
if ([delegate respondsToSelector:NSSelectorFromString(@"rimColor")]) {
rimColor = [delegate rimColor];
}
if ([delegate respondsToSelector:NSSelectorFromString(@"faceColor")]) {
faceColor = [delegate faceColor];
}
if ([delegate respondsToSelector:NSSelectorFromString(@"markColor")]) {
markColor = [delegate markColor];
}
if ([delegate respondsToSelector:NSSelectorFromString(@"fontColor")]) {
fontColor = [delegate fontColor];
}
if ([delegate respondsToSelector:NSSelectorFromString(@"hourAndMinuteHandColor")]) {
hourAndMinuteHandColor = [delegate hourAndMinuteHandColor];
}
if ([delegate respondsToSelector:NSSelectorFromString(@"secondHandColor")]) {
secondHandColor = [delegate secondHandColor];
} //秒针使用图片画出来
UIImage *img = [self drawSecondHandWithColor:secondHandColor scale:_scale frameSize:CGSizeMake(size, size) currentAngle:[self secondAngleFromDate:[NSDate new]]];
UIImageView *imgV = [[UIImageView alloc] initWithImage:img];
imgV.frame = CGRectMake(0 , 0, size, size);
[self addSubview:imgV]; //1.创建动画并指定动画属性
CABasicAnimation *basicAnimation=[CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; //2.设置动画属性初始值、结束值
// basicAnimation.fromValue=[NSNumber numberWithInt:M_PI_2];//
basicAnimation.toValue=[NSNumber numberWithFloat:2*M_PI]; //设置其他动画属性
basicAnimation.duration=60.0;//60秒转一圈
basicAnimation.autoreverses=false;//旋转后再旋转到原来的位置
basicAnimation.repeatCount = CGFLOAT_MAX;//无限循环的执行动画 imgV.layer.anchorPoint = CGPointMake(0.5, 0.5);//设置秒针的旋转中心 就是这个view的中心! //4.添加动画到图层,注意key相当于给动画进行命名,以后获得该动画时可以使用此名称获取
[imgV.layer addAnimation:basicAnimation forKey:@"Rotation"]; //当这个DDClock被创建出来的时候,就新建一个定时器,1分钟执行一次“onTimer”方法 其实这里做是不够好的 因为这样不能确保秒针走到12的时候更新 时针和分针 要想解决也很容易 最近生病 难受 不想解决了~~
[NSTimer scheduledTimerWithTimeInterval:60.0 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];
}
self.backgroundColor = [UIColor clearColor];
return self; } ///构造方法 使用默认主题
-(instancetype)initWithTheme:(DDClockTheme)theme frame:(CGRect)frame{
//防止用户在构建的时候传入的height和widt不一样 因为时钟是圆的所以强制把他们变成一样
CGFloat size = frame.size.height>frame.size.width?frame.size.height:frame.size.width;
CGRect realRect = CGRectMake(frame.origin.x, frame.origin.y, size, size);
self = [self initWithFrame:realRect];
if (self) {
_theme = theme;
_scale = realRect.size.height / DDClockSize;
_centerPoint = CGPointMake(size/2, size/2); switch (theme) { //根据主题绘制不同的颜色
case DDClockThemeDefault:
rimColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1];
faceColor = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 1];
markColor = [UIColor colorWithRed: 160.0/255.0 green: 160.0/255.0 blue: 160.0/255.0 alpha: 1];
secondHandColor = [UIColor colorWithRed: 86.0/255.0 green: 232.0/255.0 blue: 157.0/255.0 alpha: 1];
fontColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1];
hourAndMinuteHandColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1];
break; case DDClockThemeDark:
rimColor = [UIColor colorWithRed: 66.0/255 green: 66.0/255 blue: 66.0/255 alpha: 1];
faceColor = [UIColor colorWithRed: 66.0/255 green: 66.0/255 blue: 66.0/255 alpha: 1];
markColor = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 1];
secondHandColor = [UIColor colorWithRed: 32.0/255.0 green: 250.0/255.0 blue: 200.0/255.0 alpha: 1];
fontColor = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 1];
hourAndMinuteHandColor = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 1];
break; case DDClockThemeModerm:
rimColor = [UIColor colorWithRed: 60.0/255 green: 90.0/255 blue: 110.0/255 alpha: 1];
faceColor = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 1];
markColor = [UIColor colorWithRed: 160.0/255.0 green: 160.0/255.0 blue: 160.0/255.0 alpha: 1];
secondHandColor = [UIColor colorWithRed: 210.0/255.0 green: 0 blue: 10.0/255.0 alpha: 1];
fontColor = [UIColor colorWithRed: 210.0/255.0 green: 0 blue: 10.0/255.0 alpha: 1];
hourAndMinuteHandColor = [UIColor colorWithRed: 60.0/255 green: 90.0/255 blue: 110.0/255 alpha: 1];
break;
default:
rimColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1];
faceColor = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 1];
markColor = [UIColor colorWithRed: 160.0/255.0 green: 160.0/255.0 blue: 160.0/255.0 alpha: 1];
secondHandColor = [UIColor colorWithRed: 86.0/255.0 green: 232.0/255.0 blue: 157.0/255.0 alpha: 1];
fontColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1];
hourAndMinuteHandColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1];
break;
} if ([_delegate rimColor]) {
rimColor = [_delegate rimColor];
}
if ([_delegate faceColor]) {
faceColor = [_delegate faceColor];
}
if ([_delegate markColor]) {
markColor = [_delegate markColor];
}
if ([_delegate fontColor]) {
fontColor = [_delegate fontColor];
}
if ([_delegate faceColor]) {
faceColor = [_delegate faceColor];
}
if ([_delegate hourAndMinuteHandColor]) {
hourAndMinuteHandColor = [_delegate hourAndMinuteHandColor];
}
if ([_delegate secondHandColor]) {
secondHandColor = [_delegate secondHandColor];
} UIImage *img = [self drawSecondHandWithColor:secondHandColor scale:_scale frameSize:CGSizeMake(size, size) currentAngle:[self secondAngleFromDate:[NSDate new]]];
UIImageView *imgV = [[UIImageView alloc] initWithImage:img];
imgV.frame = CGRectMake(0 , 0, size, size);
[self addSubview:imgV]; //1.创建动画并指定动画属性
CABasicAnimation *basicAnimation=[CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; //2.设置动画属性初始值、结束值
// basicAnimation.fromValue=[NSNumber numberWithInt:M_PI_2];
basicAnimation.toValue=[NSNumber numberWithFloat:2*M_PI]; //设置其他动画属性
basicAnimation.duration=60.0;
basicAnimation.autoreverses=false;//旋转后再旋转到原来的位置
basicAnimation.repeatCount = CGFLOAT_MAX; imgV.layer.anchorPoint = CGPointMake(0.5, 0.5); //4.添加动画到图层,注意key相当于给动画进行命名,以后获得该动画时可以使用此名称获取
[imgV.layer addAnimation:basicAnimation forKey:@"Rotation"]; //当这个View被创建出来的时候,就新建一个定时器,1分钟执行一次“onTimer”方法
[NSTimer scheduledTimerWithTimeInterval:60.0 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];
}
self.backgroundColor = [UIColor clearColor];
return self;
} //每秒钟刷新视图一次
-(void)onTimer{
dispatch_async(dispatch_get_main_queue(), ^{
[self setNeedsDisplay];//这个方法调用后就会刷新这个View
});
} //View刷新这个方法就被调用,就会重新画出这个View
-(void)drawRect:(CGRect)rect{
[super drawRect:rect];
//获取当前的时间进行View的绘制
[self drawDDClockWithScale:_scale centerPoint:_centerPoint currentDate:[NSDate new]]; } ////画出秒针
-(UIImage*)drawSecondHandWithColor:(UIColor*)color scale:(CGFloat)scale frameSize:(CGSize)size currentAngle:(float)currentAngle{
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
//// secondHand Drawing
CGContextSaveGState(context);
CGContextTranslateCTM(context, size.height/2, size.height/2);
CGContextRotateCTM(context, (currentAngle - 90) * M_PI / 180);
CGContextScaleCTM(context, scale, scale); UIBezierPath* secondHandPath = UIBezierPath.bezierPath;
[secondHandPath moveToPoint: CGPointMake(4.96, -4.87)];
[secondHandPath addCurveToPoint: CGPointMake(6.93, -0.92) controlPoint1: CGPointMake(6.07, -3.76) controlPoint2: CGPointMake(6.73, -2.37)];
[secondHandPath addLineToPoint: CGPointMake(66.01, -0.92)];
[secondHandPath addLineToPoint: CGPointMake(66.01, 0.08)];
[secondHandPath addLineToPoint: CGPointMake(7.01, 0.08)];
[secondHandPath addCurveToPoint: CGPointMake(4.96, 5.03) controlPoint1: CGPointMake(7.01, 1.87) controlPoint2: CGPointMake(6.32, 3.66)];
[secondHandPath addCurveToPoint: CGPointMake(-4.94, 5.03) controlPoint1: CGPointMake(2.22, 7.76) controlPoint2: CGPointMake(-2.21, 7.76)];
[secondHandPath addCurveToPoint: CGPointMake(-4.94, -4.87) controlPoint1: CGPointMake(-7.68, 2.29) controlPoint2: CGPointMake(-7.68, -2.14)];
[secondHandPath addCurveToPoint: CGPointMake(4.96, -4.87) controlPoint1: CGPointMake(-2.21, -7.61) controlPoint2: CGPointMake(2.22, -7.61)];
[secondHandPath closePath];
[color setFill];
[secondHandPath fill];
CGContextRestoreGState(context);
UIImage *img = [UIImage new];
img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
} ///把当前的时间转换为时针、分针、角度
-(NSArray*)HourAndMinuteAngleFromDate:(NSDate*)date{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"HH"];//强制24小时格式
float hourf = [[formatter stringFromDate:date] floatValue];
[formatter setDateFormat:@"mm"];
float minutef = [[formatter stringFromDate:date] floatValue];
if (hourf > 12) {//大于24小时我们就减去12小时嘛 比较好算角度呀
hourf = (hourf - 12)*30 + 30*(minutef/60); //一小时30°
}else{
hourf = hourf*30 + 30*(minutef/60);
}
minutef = minutef*6;//一分钟6°
NSNumber *hour = [[NSNumber alloc] initWithInt:hourf];
NSNumber *minute = [[NSNumber alloc] initWithInt:minutef];
NSArray *arr = [[NSArray alloc] initWithObjects:hour,minute, nil];
return arr;
} //因为秒针的实时性 所以单独算出当前秒针的角度
-(float)secondAngleFromDate:(NSDate*)date{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"ss"];
float secondf = [[formatter stringFromDate:date] floatValue];
secondf = secondf*6;//一分钟6°
return secondf;
} //绘制图形的主要方法
- (void)drawDDClockWithScale: (CGFloat)scale centerPoint:(CGPoint)centerPoint currentDate:(NSDate*)currentDate;
{
NSArray *arr = [self HourAndMinuteAngleFromDate:currentDate];
NSNumber *hourAngle = (NSNumber*)[arr objectAtIndex:0];
NSNumber *minuteAngle = (NSNumber*)[arr objectAtIndex:1]; //获取绘图上下文
CGContextRef context = UIGraphicsGetCurrentContext(); //// 画出边框
CGContextSaveGState(context);
CGContextTranslateCTM(context, centerPoint.x, centerPoint.y);
CGContextScaleCTM(context, scale, scale); UIBezierPath* rimPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(-100, -100, 200, 200)];
[rimColor setFill];
[rimPath fill]; CGContextRestoreGState(context); //// 画出钟表盘
CGContextSaveGState(context);
CGContextTranslateCTM(context, centerPoint.x, centerPoint.y);
CGContextScaleCTM(context, scale, scale); UIBezierPath* facePath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(-92.99, -92.92, 186, 186)];
[faceColor setFill];
[facePath fill]; CGContextRestoreGState(context); //// 上午下午时间的判断
CGContextSaveGState(context);
CGContextTranslateCTM(context, centerPoint.x, centerPoint.y);
CGContextScaleCTM(context, scale, scale); CGRect aMPMRect = CGRectMake(-15.99, -42.92, 32, 18);
NSMutableParagraphStyle* aMPMStyle = NSMutableParagraphStyle.defaultParagraphStyle.mutableCopy;
aMPMStyle.alignment = NSTextAlignmentCenter; NSDictionary* aMPMFontAttributes = @{NSFontAttributeName: [UIFont fontWithName: @"Helvetica-Bold" size: 15], NSForegroundColorAttributeName: fontColor, NSParagraphStyleAttributeName: aMPMStyle};
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"HH"];//强制24小时格式
float hourf = [[formatter stringFromDate:currentDate] floatValue];//为了节省系统资源 延迟一分钟才会更新 因为这个方法是一分钟 调用一次的
NSString *str = hourf<12?@"AM":@"PM";
[str drawInRect: aMPMRect withAttributes: aMPMFontAttributes]; CGContextRestoreGState(context); //// 画出时针
CGContextSaveGState(context);
CGContextTranslateCTM(context, centerPoint.x, centerPoint.y);
CGContextRotateCTM(context, [hourAngle floatValue] * M_PI / 180);
CGContextScaleCTM(context, scale, scale); UIBezierPath* hourHandPath = [UIBezierPath bezierPathWithRect: CGRectMake(-4.99, -52.46, 10, 43.54)];
[hourAndMinuteHandColor setFill];
[hourHandPath fill]; CGContextRestoreGState(context); //// 画出分针
CGContextSaveGState(context);
CGContextTranslateCTM(context, centerPoint.x, centerPoint.y);
CGContextRotateCTM(context, ([minuteAngle floatValue]) * M_PI / 180);
CGContextScaleCTM(context, scale, scale); UIBezierPath* minuteHandPath = [UIBezierPath bezierPathWithRect: CGRectMake(-2.99, -64.92, 6, 55.92)];
[hourAndMinuteHandColor setFill];
[minuteHandPath fill]; CGContextRestoreGState(context); //// 画出中间的圆圈
CGContextSaveGState(context);
CGContextTranslateCTM(context, centerPoint.x, centerPoint.y);
CGContextScaleCTM(context, scale, scale); UIBezierPath* centreEmptyOvalPath = UIBezierPath.bezierPath;
[centreEmptyOvalPath moveToPoint: CGPointMake(-4.42, -4.35)];
[centreEmptyOvalPath addCurveToPoint: CGPointMake(-4.42, 4.33) controlPoint1: CGPointMake(-6.82, -1.95) controlPoint2: CGPointMake(-6.82, 1.93)];
[centreEmptyOvalPath addCurveToPoint: CGPointMake(4.26, 4.33) controlPoint1: CGPointMake(-2.02, 6.73) controlPoint2: CGPointMake(1.86, 6.73)];
[centreEmptyOvalPath addCurveToPoint: CGPointMake(4.26, -4.35) controlPoint1: CGPointMake(6.66, 1.93) controlPoint2: CGPointMake(6.66, -1.95)];
[centreEmptyOvalPath addCurveToPoint: CGPointMake(-4.42, -4.35) controlPoint1: CGPointMake(1.86, -6.75) controlPoint2: CGPointMake(-2.02, -6.75)];
[centreEmptyOvalPath closePath];
[centreEmptyOvalPath moveToPoint: CGPointMake(7.78, -7.7)];
[centreEmptyOvalPath addCurveToPoint: CGPointMake(7.78, 7.85) controlPoint1: CGPointMake(12.08, -3.41) controlPoint2: CGPointMake(12.08, 3.56)];
[centreEmptyOvalPath addCurveToPoint: CGPointMake(-7.77, 7.85) controlPoint1: CGPointMake(3.49, 12.15) controlPoint2: CGPointMake(-3.48, 12.15)];
[centreEmptyOvalPath addCurveToPoint: CGPointMake(-7.77, -7.7) controlPoint1: CGPointMake(-12.07, 3.56) controlPoint2: CGPointMake(-12.07, -3.41)];
[centreEmptyOvalPath addCurveToPoint: CGPointMake(7.78, -7.7) controlPoint1: CGPointMake(-3.48, -12) controlPoint2: CGPointMake(3.49, -12)];
[centreEmptyOvalPath closePath];
[hourAndMinuteHandColor setFill];
[centreEmptyOvalPath fill]; CGContextRestoreGState(context); //// 画出“12”
CGContextSaveGState(context);
CGContextTranslateCTM(context, centerPoint.x, centerPoint.y);
CGContextScaleCTM(context, scale, scale); CGRect text12Rect = CGRectMake(-10, -82, 21, 17);
{
NSString* textContent = @"12";
NSMutableParagraphStyle* text12Style = NSMutableParagraphStyle.defaultParagraphStyle.mutableCopy;
text12Style.alignment = NSTextAlignmentCenter; NSDictionary* text12FontAttributes = @{NSFontAttributeName: [UIFont fontWithName: @"Helvetica-Bold" size: 18], NSForegroundColorAttributeName: fontColor, NSParagraphStyleAttributeName: text12Style}; [textContent drawInRect: CGRectOffset(text12Rect, 0, (CGRectGetHeight(text12Rect) - [textContent boundingRectWithSize: text12Rect.size options: NSStringDrawingUsesLineFragmentOrigin attributes: text12FontAttributes context: nil].size.height) / 2) withAttributes: text12FontAttributes];
} CGContextRestoreGState(context); //// 画出“3”
CGContextSaveGState(context);
CGContextTranslateCTM(context, centerPoint.x, centerPoint.y);
CGContextScaleCTM(context, scale, scale); CGRect text3Rect = CGRectMake(72, -9, 12, 17);
{
NSString* textContent = @"3";
NSMutableParagraphStyle* text3Style = NSMutableParagraphStyle.defaultParagraphStyle.mutableCopy;
text3Style.alignment = NSTextAlignmentCenter; NSDictionary* text3FontAttributes = @{NSFontAttributeName: [UIFont fontWithName: @"Helvetica-Bold" size: 18], NSForegroundColorAttributeName: fontColor, NSParagraphStyleAttributeName: text3Style}; [textContent drawInRect: CGRectOffset(text3Rect, 0, (CGRectGetHeight(text3Rect) - [textContent boundingRectWithSize: text3Rect.size options: NSStringDrawingUsesLineFragmentOrigin attributes: text3FontAttributes context: nil].size.height) / 2) withAttributes: text3FontAttributes];
} CGContextRestoreGState(context); //// 画出“6”
CGContextSaveGState(context);
CGContextTranslateCTM(context, centerPoint.x, centerPoint.y);
CGContextScaleCTM(context, scale, scale); CGRect text6Rect = CGRectMake(-4, 65, 12, 17);
{
NSString* textContent = @"6";
NSMutableParagraphStyle* text6Style = NSMutableParagraphStyle.defaultParagraphStyle.mutableCopy;
text6Style.alignment = NSTextAlignmentCenter; NSDictionary* text6FontAttributes = @{NSFontAttributeName: [UIFont fontWithName: @"Helvetica-Bold" size: 18], NSForegroundColorAttributeName: fontColor, NSParagraphStyleAttributeName: text6Style}; [textContent drawInRect: CGRectOffset(text6Rect, 0, (CGRectGetHeight(text6Rect) - [textContent boundingRectWithSize: text6Rect.size options: NSStringDrawingUsesLineFragmentOrigin attributes: text6FontAttributes context: nil].size.height) / 2) withAttributes: text6FontAttributes];
} CGContextRestoreGState(context); //// 画出“9”
CGContextSaveGState(context);
CGContextTranslateCTM(context, centerPoint.x, centerPoint.y);
CGContextScaleCTM(context, scale, scale); CGRect text9Rect = CGRectMake(-82, -8, 12, 17);
{
NSString* textContent = @"9";
NSMutableParagraphStyle* text9Style = NSMutableParagraphStyle.defaultParagraphStyle.mutableCopy;
text9Style.alignment = NSTextAlignmentCenter; NSDictionary* text9FontAttributes = @{NSFontAttributeName: [UIFont fontWithName: @"Helvetica-Bold" size: 18], NSForegroundColorAttributeName: fontColor, NSParagraphStyleAttributeName: text9Style}; [textContent drawInRect: CGRectOffset(text9Rect, 0, (CGRectGetHeight(text9Rect) - [textContent boundingRectWithSize: text9Rect.size options: NSStringDrawingUsesLineFragmentOrigin attributes: text9FontAttributes context: nil].size.height) / 2) withAttributes: text9FontAttributes];
} CGContextRestoreGState(context); //// 画出表盘刻度
CGContextSaveGState(context);
CGContextTranslateCTM(context, centerPoint.x, centerPoint.y);
CGContextScaleCTM(context, scale, scale); UIBezierPath* markPath = UIBezierPath.bezierPath;
[markPath moveToPoint: CGPointMake(-2, -85)];
[markPath addLineToPoint: CGPointMake(2, -85)];
[markPath addLineToPoint: CGPointMake(2, -93)];
[markPath addLineToPoint: CGPointMake(-2, -93)];
[markPath addLineToPoint: CGPointMake(-2, -85)];
[markPath closePath];
[markPath moveToPoint: CGPointMake(-1, 93)];
[markPath addLineToPoint: CGPointMake(3, 93)];
[markPath addLineToPoint: CGPointMake(3, 85)];
[markPath addLineToPoint: CGPointMake(-1, 85)];
[markPath addLineToPoint: CGPointMake(-1, 93)];
[markPath closePath];
[markPath moveToPoint: CGPointMake(-45, -72.15)];
[markPath addLineToPoint: CGPointMake(-41.54, -74.15)];
[markPath addLineToPoint: CGPointMake(-45.54, -81.08)];
[markPath addLineToPoint: CGPointMake(-49, -79.08)];
[markPath addLineToPoint: CGPointMake(-45, -72.15)];
[markPath closePath];
[markPath moveToPoint: CGPointMake(44.87, 81.5)];
[markPath addLineToPoint: CGPointMake(48.33, 79.5)];
[markPath addLineToPoint: CGPointMake(44.33, 72.57)];
[markPath addLineToPoint: CGPointMake(40.87, 74.57)];
[markPath addLineToPoint: CGPointMake(44.87, 81.5)];
[markPath closePath];
[markPath moveToPoint: CGPointMake(-75.07, -40)];
[markPath addLineToPoint: CGPointMake(-73.07, -43.46)];
[markPath addLineToPoint: CGPointMake(-80, -47.46)];
[markPath addLineToPoint: CGPointMake(-82, -44)];
[markPath addLineToPoint: CGPointMake(-75.07, -40)];
[markPath closePath];
[markPath moveToPoint: CGPointMake(79.58, 48.13)];
[markPath addLineToPoint: CGPointMake(81.58, 44.67)];
[markPath addLineToPoint: CGPointMake(74.65, 40.67)];
[markPath addLineToPoint: CGPointMake(72.65, 44.13)];
[markPath addLineToPoint: CGPointMake(79.58, 48.13)];
[markPath closePath];
[markPath moveToPoint: CGPointMake(-85, 2)];
[markPath addLineToPoint: CGPointMake(-85, -2)];
[markPath addLineToPoint: CGPointMake(-93, -2)];
[markPath addLineToPoint: CGPointMake(-93, 2)];
[markPath addLineToPoint: CGPointMake(-85, 2)];
[markPath closePath];
[markPath moveToPoint: CGPointMake(93, 1)];
[markPath addLineToPoint: CGPointMake(93, -3)];
[markPath addLineToPoint: CGPointMake(85, -3)];
[markPath addLineToPoint: CGPointMake(85, 1)];
[markPath addLineToPoint: CGPointMake(93, 1)];
[markPath closePath];
[markPath moveToPoint: CGPointMake(-72.57, 44)];
[markPath addLineToPoint: CGPointMake(-74.57, 40.54)];
[markPath addLineToPoint: CGPointMake(-81.5, 44.54)];
[markPath addLineToPoint: CGPointMake(-79.5, 48)];
[markPath addLineToPoint: CGPointMake(-72.57, 44)];
[markPath closePath];
[markPath moveToPoint: CGPointMake(81.08, -45.87)];
[markPath addLineToPoint: CGPointMake(79.08, -49.33)];
[markPath addLineToPoint: CGPointMake(72.15, -45.33)];
[markPath addLineToPoint: CGPointMake(74.15, -41.87)];
[markPath addLineToPoint: CGPointMake(81.08, -45.87)];
[markPath closePath];
[markPath moveToPoint: CGPointMake(-39.67, 75.07)];
[markPath addLineToPoint: CGPointMake(-43.13, 73.07)];
[markPath addLineToPoint: CGPointMake(-47.13, 80)];
[markPath addLineToPoint: CGPointMake(-43.67, 82)];
[markPath addLineToPoint: CGPointMake(-39.67, 75.07)];
[markPath closePath];
[markPath moveToPoint: CGPointMake(48.46, -79.58)];
[markPath addLineToPoint: CGPointMake(45, -81.58)];
[markPath addLineToPoint: CGPointMake(41, -74.65)];
[markPath addLineToPoint: CGPointMake(44.46, -72.65)];
[markPath addLineToPoint: CGPointMake(48.46, -79.58)];
[markPath closePath];
[markColor setFill];
[markPath fill]; CGContextRestoreGState(context);
} @end

xcode6.1 SDK8.1测试没问题!

代码中已经有无比详细的注释,而且该控件简单地令人发指~ 我相信你看的懂得!

我想肯定有同学已经排着队,准备好了板砖,鸡蛋什么的,“博主!你妹!说好的无比迅速敏捷地开发iOS超精美控件 哪里迅速哪里敏捷?说好的奇淫巧技呢?”

都说心急吃不了热豆腐,我有说文章结束了么?文章只是出轨而已了……

PaintCode

代码是写出来了, 但是在


-(void)drawRect:(CGRect)rect

方法中一笔一笔的勾画出来,确实是累人~

所以我要祭出这次文章的纯24K真大杀器——PaintCode

图3

为何要称PaintCode为终极大杀器?因为它真的很凶!如果说我们刚刚的项目需要花2~3个小时才能完成 而有了PaintCode之后我们只需要10~20分钟!!!就问你怕不怕!!!

售价$99的PaintCode用起来就是爽!

我突然想起自己的一个故事,有一年上大学,父亲到车站来送我,临上车前,父亲叮嘱我等他一会儿他要过铁道对面要给我买点东西,说我一个人过日子会很艰难,我看见他戴着黑布小帽,穿着黑布大马褂,深青布棉袍,蹒跚地走到铁道边,慢慢探身下去,尚不大难。可是他穿过铁道,要爬上那边月台,就不容易了。他用两手攀着上面,两脚再向上缩;他肥胖的身子向左微倾,显出努力的样子。这时我看见他的背影,我的泪很快地流下来了。我赶紧拭干了泪。怕他看见,也怕别人看见。我再向外看时,他已抱了一个黑塑料袋子往回走了。过铁道时,他先将塑料袋散放在地上,自己慢慢爬下,再抱起塑料袋走。到这边时,我赶紧去搀他。他和我走到车上,将塑料袋一股脑儿放在我的皮大衣上:“最新的全是外国的动作片、游戏、音乐光盘,好好照顾自己”,想起老父亲微薄的退休金,我就有点气愤:“爸,你怎么……”,父亲赶忙凑到我的耳边:“D版的,八国联军当年抢得钱是该要回来的”,我:“……”

好了我的故事讲完了 你们应该知道怎么找PaintCode了额

我么开始PaintCode之旅吧

打开Paint

图4

就像PS一样只要你画的出,就能生成代码(支持swift哦)

我们就试试画出DDClock来吧

选中Oval

图5

按住shift键拖出一个规则的圆形 ,填充颜色,这个就是代码中的rimPath

图6

再次选中Oval,同样的方法在拖一个圆出来,

图7

这个就是代码中的facePath。

在PaintCode中尽量将所有的图形、颜色都自己取一个名字,比如我把第一个Oval取名字rim,第二个Oval取名字face

这样表盘的边框和中间都出来了额,接下来就是表盘的刻度了

选中rect

图8

拖出其中的一个小刻度

图9

然后选中这个小刻度复制出另一个小刻度,放到第一个刻度的对面,就像这样

图10

然后按住shift键 同时选中这两个小刻度,点击工具栏的Union

图11

这样两个小刻度就成为了一个对象,这时点击右侧的Transforms,就会出现旋转图形的操作,把旋转中心(图12中绿色的瞄准星)拖到钟表的中心位置

图12

这样设置Rotation的参数就可以围绕整个钟表旋转这个刻度了,所以马上同时复制这个刻度5份,分别操作旋转,让它们分别旋转30、60、90、120、150这样所有的刻度都出来了,然后再一次性的选中所有刻度Union一次,把所有刻度合并成一个图形。

图13

接下来就选中Text工具

图14

选中恰当的字体和大小,画出刻度值和上下午提示的AM/PM

图15

最后是时针、分针和秒针了,做法是雷同的,聪明的你肯定知道该怎么做了,反正就是使用规则图形,通过Union、Intersection、Difference的操作产生不规则的图形

图16

图17

图18

最后看我的项目大体情况;

到了这一步其实就可以直接复制代码走人就OK拉

然后稍微谢谢项目的逻辑代码,测试,OK啦,是不是把2、3个小时的事情10分钟完成了?哈哈哈

其实PaintCode的强大远不止于此,里面的Variables的功能,可以将图形中的某个值设置成变量,比如代码中的hourAngle、 minuteAngle 、 secondAngle 等,DDClock目前的大小的是固定的200x200,其实使用Variables添加scale的变量,还可以动态的修改所有图形的大小!当然还有Frame的使用啦……

后记

对于PaintCode博主也只是浅尝而止,更多强大的功能,同学们还是自己挖掘吧。

这里附上官网的地址,PaintCode 里面有视频教程,文档等(视频是油管网的,所以需要FQ,呵呵,你懂的)

这里也附上我写的项目源代码 DDClock(尼玛!github使用代理比直接访问更快,你能忍?)

这个礼拜,完成了毕设的主题和一些细节,大概是设计一套移动客户端和后台服务器安全交互的方案,涉及到各种安全通信,可靠性传输,内容加解密等内容,我会把这个设想写到博客上的;

女朋友回老家了,剩下自己一个人撸啊撸T_T;

天杀的12306买了两天都没买到回家的票,明明买不到票,却还要写着有余票,哎,最后我决定坐头等舱回家了~

无比迅速敏捷地开发iOS超精美控件的更多相关文章

  1. iOS开发UI篇—UIScrollView控件实现图片缩放功能

    iOS开发UI篇—UIScrollView控件实现图片缩放功能 一.缩放 1.简单说明: 有些时候,我们可能要对某些内容进行手势缩放,如下图所示 UIScrollView不仅能滚动显示大量内容,还能对 ...

  2. iOS开发UI篇—UIScrollView控件介绍

    iOS开发UI篇—UIScrollView控件介绍 一.知识点简单介绍 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 ...

  3. iOS开发UI篇—UITableview控件简单介绍

    iOS开发UI篇—UITableview控件简单介绍 一.基本介绍 在众多移动应⽤用中,能看到各式各样的表格数据 . 在iOS中,要实现表格数据展示,最常用的做法就是使用UITableView,UIT ...

  4. iOS开发UI篇—UITableview控件基本使用

    iOS开发UI篇—UITableview控件基本使用 一.一个简单的英雄展示程序 NJHero.h文件代码(字典转模型) #import <Foundation/Foundation.h> ...

  5. iOS开发UI篇—UITableview控件使用小结

    iOS开发UI篇—UITableview控件使用小结 一.UITableview的使用步骤 UITableview的使用就只有简单的三个步骤: 1.告诉一共有多少组数据 方法:- (NSInteger ...

  6. iOS开发UI篇—UIScrollView控件实现图片轮播

    iOS开发UI篇—UIScrollView控件实现图片轮播 一.实现效果 实现图片的自动轮播            二.实现代码 storyboard中布局 代码: #import "YYV ...

  7. 【转】 iOS开发UI篇—UIScrollView控件实现图片轮播

    原文:http://www.cnblogs.com/wendingding/p/3763527.html iOS开发UI篇—UIScrollView控件实现图片轮播 一.实现效果 实现图片的自动轮播 ...

  8. ios开发中关闭textview控件的虚拟键盘

    在ios开发中,textfield控件在点击的时候出现虚拟键盘,关掉虚拟键盘可以通过虚拟键盘中的done button和点击view中的任意地方来关闭虚拟键盘. 1.第一种方法是textfield控件 ...

  9. 从0到1搭建移动App功能自动化测试平台(2):操作iOS应用的控件

    转自:http://debugtalk.com/post/build-app-automated-test-platform-from-0-to-1-Appium-interrogate-iOS-UI ...

随机推荐

  1. jquery text() html() val()

    test text() 返回 test html() 返回 test val() 没值, val() 适用于有value属性的元素, 例如: input

  2. Jdeveloper下Svn的使用

    Jdeveloper下Svn的使用 官方pdf:jdeveloper使用svn 官方网地址:http://www.oracle.com/technetwork/cn/java/subversion-0 ...

  3. 查看binlog的简单方法!

    今天学到一个牛逼的东西,不用打开binlog文件就可以查看binlog里的event事件. 命令为:show binlog events in 'mysql-bin.000001' from 4 li ...

  4. 用Hash Table(哈希散列表)实现统计文本每个单词重复次数(频率)

    哈希表在查找方面有非常大应用价值,本文记录一下利用哈希散列表来统计文本文件中每个单词出现的重复次数,这个需求当然用NLP技术也很容易实现. 一.基本介绍 1.Hash Key值:将每个单词按照字母组成 ...

  5. 全球数据库-->基金/管理产品-->分类/行业平均-->开放式分类

    SecID 招募书中所定净费率 换手率% 回报日期(每日) 计价货币 回报-本月以来(每日)计价货币 回报-本季以来(每日)计价货币 回报-本年以来(每日)计价货币 回报-1日(每日)计价货币 回报- ...

  6. 尝试编写的rabbitmq+spring 框架

    spring有自己的一套框架与消息队列结合使用http://projects.spring.io/spring-amqp/,这个接下来会好好的研究一下. 在领导的帮助下,终于勉强写完了这个消息队列的框 ...

  7. python 中numpy的var,std及cov

    var:表示方差, 即各项-均值的平方求和后再除以N , std:表示标准差,是var的平方根. cov:协方差 ,与var类似,但是除以(N-1)

  8. [GO]go使用etcd

    package main import ( "go.etcd.io/etcd/clientv3" //笔者在使用clientv3的时间曾经使用过github.com/coreos/ ...

  9. unittest单元测试框架之coverage代码覆盖率统计

    什么是coveage? coverage是一个检测单元测试覆盖率的工具,即检查你的测试用例是否覆盖到了所有的代码.当你通过pip install coverage成功安装完coverage后,就会在p ...

  10. Oracle学习笔记(四)

    六.约束 1.约束的作用 定义规则:什么数据可以输入,什么不可以 确保完整性:数据的精确性和可靠性 2.Oracle五个重要的约束: 非空约束.主键约束.外键约束.检查约束.唯一约束. (1)非空约束 ...