20.0. Introduction(Graphics and Animations)
你应该看过很多界面很漂亮的应用,他们给你留下了很深的印象。iOS runtime 和 Cocoa 使你能够以相对简单的代码实现漂亮的界面和动画。当然了,漂亮的界面和动画是程序员和美工共同劳动的结果。在本章中,你将看到借助一些简单的编程技巧,你能实现什么。
Cocoa应用中,应用是由windows和views组成。一个应用至少有一个window,但可以有很多个view。window是UIWindow类。通常应用就是在window上放置很多的view。如buttons,labels,images 等。这些控件由UIKit来绘画。
会不会很难理解呢,不过通过本章,相信你将会慢慢了解他们。
苹果已经提供了一些强悍的框架来绘图,稍微看下:
UIKit: 创建view, window,button和其他UI相关控件,包括由某些低级api合成的高级api。
Quartz 2D: iOS绘画主引擎;UIKit使用的是Quartz
Core Graphics:支持图像导入,绘制等得框架
Core Animation:iOS 动画实现
画图中最重要的一个概念是point 和 pixel的区别。可能大家已经很熟悉pixel,那什么是point呢?They’re the device-independent counterpart of pixels。当写代码时设置的宽高,iOS把它当做point对待,而不是pixel
。比如你想填充,iPhone 5的整个屏幕,你设置其宽度为320,高度为568。但是其屏幕的实际分辨率是640*1136。这就是point的厉害之处,它处理了缩放因子(content scale factor)
缩放因子是一个浮点值,是一个逻辑的point到实际的pixel的一个转换值,iPhone 5的缩放因子是2.0。
-------------我的理解,这里的point其实相当于Android 中得dp,dip--------------------
本章中,我们将使用view来画图形,字符串等
为了运行本章的代码,需要你子类化UIView,并把控制器的view的类名改成新建的View
20.1. Enumerating and Loading Fonts
枚举内置字体
- (void) enumerateFonts{
for (NSString *familyName in [UIFont familyNames]){
NSLog(@"Font Family = %@", familyName);
for (NSString *fontName in [UIFont fontNamesForFamilyName:familyName]){
NSLog(@"\tfontName=%@", fontName);
}
}
}
打印:
2014-07-30 15:47:25.088 cookbook7_20[485:a0b] Font Family = Thonburi
2014-07-30 15:47:25.089 cookbook7_20[485:a0b] fontName=Thonburi-Bold
2014-07-30 15:47:25.089 cookbook7_20[485:a0b] fontName=Thonburi
2014-07-30 15:47:25.090 cookbook7_20[485:a0b] fontName=Thonburi-Light
2014-07-30 15:47:25.090 cookbook7_20[485:a0b] Font Family = Snell Roundhand
2014-07-30 15:47:25.091 cookbook7_20[485:a0b] fontName=SnellRoundhand-Black
2014-07-30 15:47:25.091 cookbook7_20[485:a0b] fontName=SnellRoundhand-Bold
2014-07-30 15:47:25.092 cookbook7_20[485:a0b] fontName=SnellRoundhand
2014-07-30 15:47:25.092 cookbook7_20[485:a0b] Font Family = Academy Engraved LET
2014-07-30 15:47:25.093 cookbook7_20[485:a0b] fontName=AcademyEngravedLetPlain
2014-07-30 15:47:25.093 cookbook7_20[485:a0b] Font Family = Marker Felt
2014-07-30 15:47:25.093 cookbook7_20[485:a0b] fontName=MarkerFelt-Thin
2014-07-30 15:47:25.094 cookbook7_20[485:a0b] fontName=MarkerFelt-Wide
2014-07-30 15:47:25.094 cookbook7_20[485:a0b] Font Family = Avenir
。。。。。。
字体被分成了家族,也就有了家族名称和各个字体的名称。
知道了字体名称,就可以导入字体了
-(void)testLoadfont
{
__unused UIFont *font = [UIFont fontWithName:@"Thonburi-Bold"
size:12.0f];
NSLog(@"font=%@",font);
}
打印:
2014-07-30 15:53:18.478 cookbook7_20[506:a0b] font=<UICTFont: 0x89652a0> font-family: "Thonburi"; font-weight: bold; font-style: normal; font-size: 12.00pt
当然了,也可以用systemFontOfSize: boldSystemFontOfSize:等来导入字体,系统默认字体是Helvetica.
20.2. Drawing Text
画字符串
使用NSString的drawAtPoint:withFont:
#import "View.h"
@implementation View
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
UIFont *helveticaBold = [UIFont fontWithName:@"HelveticaNeue-Bold"
size:40.0f];
NSString *myString = @"Some String";
//NS_AVAILABLE_IOS(7_0);
[myString drawAtPoint:CGPointMake(40, 180)
withAttributes:@{
NSFontAttributeName : helveticaBold
}];
}
@end
运行结果
20.3. Constructing, Setting, and Using Colors
创建设置使用颜色
-(void)drawRect:(CGRect)rect
{
/* Load the color */
UIColor *magentaColor =[UIColor colorWithRed:0.5f
green:0.0f
blue:0.5f
alpha:1.0f];
/* Set the color in the graphical context */
[magentaColor set];
/* Load the font */
UIFont *helveticaBold = [UIFont fontWithName:@"HelveticaNeue-Bold"
size:30.0f];
/* Our string to be drawn */
NSString *myString = @"I Learn Really Fast";
/* Draw the string using the font. The color has
already been set */
[myString drawAtPoint:CGPointMake(25, 190)
withAttributes:@{
NSFontAttributeName : helveticaBold
}];
}
运行:
使用drawWithRect:options:attributes:context:来限制显示区域
-(void)drawRect:(CGRect)rect
{
/* Load the color */
UIColor *magentaColor = [UIColor colorWithRed:0.5f
green:0.0f
blue:0.5f
alpha:1.0f];
/* Set the color in the graphical context */
[magentaColor set];
/* Load the font */
UIFont *helveticaBold = [UIFont boldSystemFontOfSize:30];
/* Our string to be drawn */
NSString *myString = @"I Learn Really Fast";
/* Draw the string using the font. The color has
already been set */
[myString drawWithRect:CGRectMake(100, /* x */
120, /* y */
100, /* width */
200)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{
NSFontAttributeName : helveticaBold
}
context:nil];
}
运行:
UIColor是对CGColor的封装,深入core Graphics的底层,将获得更多的操控。
如何获取颜色的各个色值
-(void)drawRect:(CGRect)rect
{
/* Load the color */
UIColor *steelBlueColor = [UIColor colorWithRed:0.3f
green:0.4f
blue:0.6f
alpha:1.0f];
CGColorRef colorRef = steelBlueColor.CGColor;
const CGFloat *components = CGColorGetComponents(colorRef);
NSUInteger componentsCount = CGColorGetNumberOfComponents(colorRef);
NSUInteger counter = 0; for (counter = 0;
counter < componentsCount;
counter++){
NSLog(@"Component %lu = %.02f",
(unsigned long)counter + 1, components[counter]);
}
}
运行:
2014-07-30 17:18:11.609 cookbook7_20[809:a0b] Component 1 = 0.30
2014-07-30 17:18:11.609 cookbook7_20[809:a0b] Component 2 = 0.40
2014-07-30 17:18:11.610 cookbook7_20[809:a0b] Component 3 = 0.60
2014-07-30 17:18:11.610 cookbook7_20[809:a0b] Component 4 = 1.00
20.4. Drawing Images
画图
1,打开xcode的目录,找到xcode.icns文件,复制出来
2,打开xcode.icns文件,右键导出页面1,png保存
3,工程中引用xcode.png文件
-(void)drawRect:(CGRect)rect
{
UIImage *image = [UIImage imageNamed:@"Xcode"];
if (image != nil){
NSLog(@"Successfully loaded the image.");
} else {
NSLog(@"Failed to load the image.");
}
/* Assuming the image is in your app bundle and we can load it */
UIImage *xcodeIcon = [UIImage imageNamed:@"Xcode"];
[xcodeIcon drawAtPoint:CGPointMake(0.0f,
20.0f)];
[xcodeIcon drawInRect:CGRectMake(50.0f,
10.0f,
40.0f,
35.0f)];
}
运行:
2014-07-30 17:34:14.143 cookbook7_20[886:a0b] Successfully loaded the image.
20.5. Constructing Resizable Images
创建可变大小的图片 resizableImageWithCapInsets
当图片的大小与显示控件的大小不一致,又想让图片充满整个控件,该怎么办呢?可以用平铺的方式,也可以用拉伸的方式,本节介绍平铺的方式。
可能一般的平铺和拉伸你都懂的。但本章介绍的这种你可能不懂。他可以指定对图片中的某块区域进行平铺和拉伸,而不是对整张图片
这样做的好处是,你可以在保持图片的4个角不变形。
nine-part images
分成九部分图之后,就可以以一种更好的方式来调整图片的大小。
当需要resize图片大小的时候4个角是的部分是不变的。其他部分如下:
Top edge、Bottom edge:只变宽度,不变高度
Left edge、Right edge:只变高度,不变宽度
Center:宽度,高度都会改变
通过UIEdgeInsets可以吧一张图分成9部分
typedef struct UIEdgeInsets {
CGFloat top, left, bottom, right;
} UIEdgeInsets;
#import "ViewController.h"
@interface ViewController ()
@property (strong, nonatomic) UIButton *button;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self testresizableImageWithCapInsets];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIButton *)getButton
{
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(0.0f, 0.0f, 108, 48)];
/* Set the title of the button */
[button setTitle:@"Stretched Image on Button"
forState:UIControlStateNormal];
/* Adjust the font for our text */
button.titleLabel.font = [UIFont systemFontOfSize:15.0f];
return button;
}
-(UIButton *)getstretchButton
{
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(0.0f, 0.0f, 300, 200)];
/* Set the title of the button */
[button setTitle:@"Stretched Image on Button"
forState:UIControlStateNormal];
/* Adjust the font for our text */
button.titleLabel.font = [UIFont systemFontOfSize:15.0f];
return button;
}
-(void)testresizableImageWithCapInsets
{
UIButton* button = [self getButton];
UIImage * image = [UIImage imageNamed:@"button2"];
[button setBackgroundImage:image forState:UIControlStateNormal];
[self.view addSubview:button];
button.center = CGPointMake(self.view.center.x, self.view.center.y - 100);
UIButton * stretchButton = [self getstretchButton];
UIEdgeInsets edgeInsets;
edgeInsets.left = 40.0f;
edgeInsets.top = 13;
edgeInsets.right =40.0f;
edgeInsets.bottom = 10;
//平铺
UIImage * stretchImage = [image resizableImageWithCapInsets:edgeInsets resizingMode:UIImageResizingModeTile];
//拉伸
// UIImage * stretchImage = [image resizableImageWithCapInsets:edgeInsets resizingMode:UIImageResizingModeStretch];
[stretchButton setBackgroundImage:stretchImage forState:UIControlStateNormal];
[self.view addSubview:stretchButton];
stretchButton.center = CGPointMake(self.view.center.x, self.view.center.y + 100);
}
@end
原始图:
运行后:
使用拉伸的效果
20.6. Drawing Lines
划线
CGContextMoveToPoint
CGContextAddLineToPoint
- (void)testdraw
{
[self drawRooftopAtTopPointof:CGPointMake(160.0f, 40.0f)
textToDisplay:@"Miter"
lineJoin:kCGLineJoinMiter];
[self drawRooftopAtTopPointof:CGPointMake(160.0f, 180.0f)
textToDisplay:@"Bevel"
lineJoin:kCGLineJoinBevel];
[self drawRooftopAtTopPointof:CGPointMake(160.0f, 320.0f)
textToDisplay:@"Round"
lineJoin:kCGLineJoinRound];
}
- (void) drawRooftopAtTopPointof:(CGPoint)paramTopPoint
textToDisplay:(NSString *)paramText
lineJoin:(CGLineJoin)paramLineJoin{
/* Set the color that we want to use to draw the line */
[[UIColor brownColor] set];
/* Get the current graphics context */
CGContextRef currentContext = UIGraphicsGetCurrentContext();
/* Set the line join */
CGContextSetLineJoin(currentContext,
paramLineJoin);
/* Set the width for the lines */
CGContextSetLineWidth(currentContext,
20.0f);
/* Start the line at this point */
CGContextMoveToPoint(currentContext,
paramTopPoint.x - 140,
paramTopPoint.y + 100);
/* And end it at this point */
CGContextAddLineToPoint(currentContext,
paramTopPoint.x,
paramTopPoint.y);
/* Extend the line to another point to
make the rooftop */
CGContextAddLineToPoint(currentContext,
paramTopPoint.x + 140,
paramTopPoint.y + 100);
/* Use the context's current color to draw the lines */
CGContextStrokePath(currentContext);
/* Draw the text in the rooftop using a black color */
[[UIColor blackColor] set];
/* Now draw the text */
CGPoint drawingPoint = CGPointMake(paramTopPoint.x - 40.0f,
paramTopPoint.y + 60.0f);
UIFont *font = [UIFont boldSystemFontOfSize:30.0f];
[paramText drawAtPoint:drawingPoint
withAttributes:@{NSFontAttributeName : font}];
}
20.7. Constructing Paths
构建路径
#import "View.h"
@implementation View
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)drawRect:(CGRect)rect{
/* Create the path */
CGMutablePathRef path = CGPathCreateMutable();
/* How big is our screen? We want the X to cover the whole screen */
CGRect screenBounds = [[UIScreen mainScreen] bounds];
/* Start from top-left */
CGPathMoveToPoint(path,
NULL,
screenBounds.origin.x,
screenBounds.origin.y);
/* Draw a line from top-left to bottom-right of the screen */
CGPathAddLineToPoint(path,
NULL,
screenBounds.size.width,
screenBounds.size.height);
/* Start another line from top-right */
CGPathMoveToPoint(path,
NULL,
screenBounds.size.width,
screenBounds.origin.y);
/* Draw a line from top-right to bottom-left */
CGPathAddLineToPoint(path,
NULL,
screenBounds.origin.x,
screenBounds.size.height);
/* Get the context that the path has to be drawn on */
CGContextRef currentContext = UIGraphicsGetCurrentContext();
/* Add the path to the context so we can
draw it later */
CGContextAddPath(currentContext,
path);
/* Set the blue color as the stroke color */
[[UIColor blueColor] setStroke];
/* Draw the path with stroke color */
CGContextDrawPath(currentContext,
kCGPathStroke);
/* Finally release the path object */
CGPathRelease(path);
}
@end
20.8. Drawing Rectangles
画矩形
- (void)drawRect:(CGRect)rect{
/* Create the path first. Just the path handle. */
CGMutablePathRef path = CGPathCreateMutable();
CGRect rectangle = CGRectMake(200.0f,
330.0f,
100.0f,
100.0f);
/* Add the rectangle to the path */
CGPathAddRect(path,
NULL,
rectangle);
/* Here are our first rectangle boundaries */
CGRect rectangle1 = CGRectMake(10.0f,
30.0f,
200.0f,
300.0f);
/*And the second rectangle */
CGRect rectangle2 = CGRectMake(40.0f,
100.0f,
90.0f,
300.0f);
/* Put both rectangles into an array */
CGRect rectangles[2] = {
rectangle1, rectangle2
};
/* Add the rectangles to the path */
CGPathAddRects(path,
NULL,
(const CGRect *)&rectangles, 2);
/* Get the handle to the current context */
CGContextRef currentContext = UIGraphicsGetCurrentContext();
/* Add the path to the context */
CGContextAddPath(currentContext,
path);
/* Set the fill color to cornflower blue */
[[UIColor colorWithRed:0.20f
green:0.60f
blue:0.80f
alpha:1.0f] setFill];
/* Set the stroke color to black */
[[UIColor blackColor] setStroke];
/* Set the line width (for the stroke) to 5 */
CGContextSetLineWidth(currentContext,
5.0f);
/* Stroke and fill the path on the context */
CGContextDrawPath(currentContext,
kCGPathFillStroke);
/* Dispose of the path */
CGPathRelease(path);
}
结果:
20.9. Adding Shadows to Shapes
阴影
来画两个矩形,第一个要阴影,第二个不要阴影
- (void) drawRect:(CGRect)rect{
[self drawRectAtTopOfScreen];
[self drawRectAtBottomOfScreen];
}
- (void) drawRectAtTopOfScreen{
/* Get the handle to the current context */
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSetShadowWithColor(currentContext,
CGSizeMake(10.0f, 10.0f),
20.0f,
[[UIColor grayColor] CGColor]);
/* Create the path first. Just the path handle. */
CGMutablePathRef path = CGPathCreateMutable();
/* Here are our rectangle boundaries */
CGRect firstRect = CGRectMake(55.0f,
60.0f,
150.0f,
150.0f);
/* Add the rectangle to the path */
CGPathAddRect(path,
NULL,
firstRect);
/* Add the path to the context */
CGContextAddPath(currentContext,
path);
/* Set the fill color to cornflower blue */
[[UIColor colorWithRed:0.20f
green:0.60f
blue:0.80f
alpha:1.0f] setFill];
/* Fill the path on the context */
CGContextDrawPath(currentContext,
kCGPathFill);
/* Dispose of the path */
CGPathRelease(path);
}
- (void) drawRectAtBottomOfScreen{
/* Get the handle to the current context */
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGMutablePathRef secondPath = CGPathCreateMutable();
CGRect secondRect = CGRectMake(150.0f,
250.0f,
100.0f,
100.0f);
CGPathAddRect(secondPath,
NULL,
secondRect);
CGContextAddPath(currentContext,
secondPath);
[[UIColor purpleColor] setFill];
CGContextDrawPath(currentContext,
kCGPathFill);
CGPathRelease(secondPath);
}
运行:
我们发现,第二个也有阴影了,这是因为在画第一个的时候,其改变的属性应用到第二个上面了。
如何让第二个没有阴影呢?
方法一:先画第二个,再画第一个,不过这方法比较山寨
方法二:再画第一个之前先把graphics context的状态保存,画完之后再恢复回去。
- (void) drawRectAtTopOfScreen{
/* Get the handle to the current context */
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetShadowWithColor(currentContext,
CGSizeMake(10.0f, 10.0f),
20.0f,
[[UIColor grayColor] CGColor]);
/* Create the path first. Just the path handle. */
CGMutablePathRef path = CGPathCreateMutable();
/* Here are our rectangle boundaries */
CGRect firstRect = CGRectMake(55.0f,
60.0f,
150.0f,
150.0f);
/* Add the rectangle to the path */
CGPathAddRect(path,
NULL,
firstRect);
/* Add the path to the context */
CGContextAddPath(currentContext,
path);
/* Set the fill color to cornflower blue */
[[UIColor colorWithRed:0.20f
green:0.60f
blue:0.80f
alpha:1.0f] setFill];
/* Fill the path on the context */
CGContextDrawPath(currentContext,
kCGPathFill);
/* Dispose of the path */
CGPathRelease(path);
/* Restore the context to how it was
when we started */
CGContextRestoreGState(currentContext);
}
20.10. Drawing Gradients
渐变颜色
CGGradientCreateWithColor
- (void)drawRect:(CGRect)rect{
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
UIColor *startColor = [UIColor orangeColor];
CGFloat *startColorComponents =
(CGFloat *)CGColorGetComponents([startColor CGColor]);
UIColor *endColor = [UIColor blueColor];
CGFloat *endColorComponents =
(CGFloat *)CGColorGetComponents([endColor CGColor]);
CGFloat colorComponents[8] = {
/* Four components of the orange color (RGBA) */
startColorComponents[0],
startColorComponents[1],
startColorComponents[2],
startColorComponents[3], /* First color = orange */
/* Four components of the blue color (RGBA) */
endColorComponents[0],
endColorComponents[1],
endColorComponents[2],
endColorComponents[3], /* Second color = blue */
};
CGFloat colorIndices[2] = {
0.0f, /* Color 0 in the colorComponents array */
1.0f, /* Color 1 in the colorComponents array */
};
CGGradientRef gradient = CGGradientCreateWithColorComponents
(colorSpace,
(const CGFloat *)&colorComponents,
(const CGFloat *)&colorIndices,
2);
CGColorSpaceRelease(colorSpace);
CGPoint startPoint, endPoint;
startPoint = CGPointMake(120,
260);
endPoint = CGPointMake(200.0f,
220);
// startPoint = CGPointMake(50, 50);
// endPoint = CGPointMake(270, 430);
CGContextDrawLinearGradient (currentContext,
gradient,
startPoint,
endPoint,
kCGGradientDrawsBeforeStartLocation |//自己换成0试试
kCGGradientDrawsAfterEndLocation);
CGGradientRelease(gradient);
CGContextRestoreGState(currentContext);
}
运行:
20.11. Moving Shapes Drawn on Graphic Contexts
移动所画的内容
CGAffineTransformMakeTranslation
- (void)drawRect:(CGRect)rect{
/* Create the path first. Just the path handle. */
CGMutablePathRef path = CGPathCreateMutable();
/* Here are our rectangle boundaries */
CGRect rectangle = CGRectMake(10.0f,
30.0f,
200.0f,
300.0f);
/* We want to displace the rectangle to the right by
100 points but want to keep the y position
untouched */
CGAffineTransform transform1 = CGAffineTransformMakeTranslation(100.0f,
0.0f);
CGAffineTransform transform2 = CGAffineTransformMakeRotation(0.1);
CGAffineTransform transform = CGAffineTransformConcat(transform1, transform2);
NSLog(@"transform1=%@", NSStringFromCGAffineTransform(transform1));
NSLog(@"transform2=%@", NSStringFromCGAffineTransform(transform2));
NSLog(@"transform=%@", NSStringFromCGAffineTransform(transform));
/* Add the rectangle to the path */
CGPathAddRect(path,
&transform,
rectangle);
/* Get the handle to the current context */
CGContextRef currentContext = UIGraphicsGetCurrentContext();
/* Add the path to the context */
CGContextAddPath(currentContext, path);
/* Set the fill color to cornflower blue */
[[UIColor colorWithRed:0.20f
green:0.60f
blue:0.80f
alpha:1.0f] setFill]; /* Set the stroke color to brown */
[[UIColor brownColor] setStroke];
/* Set the line width (for the stroke) to 5 */
CGContextSetLineWidth(currentContext,5.0f);
/* Stroke and fill the path on the context */
CGContextDrawPath(currentContext,kCGPathFillStroke);
/* Dispose of the path */
CGPathRelease(path);
}
运行:
2014-08-06 15:45:51.579 cookbook7_20[647:a0b] transform=[1, 0, 0, 1, 100, 0]
20.12. Scaling Shapes Drawn on Graphic Contexts
- (void)drawRect:(CGRect)rect{
/* Create the path first. Just the path handle. */
CGMutablePathRef path = CGPathCreateMutable();
/* Here are our rectangle boundaries */
CGRect rectangle = CGRectMake(10.0f,
30.0f,
200.0f,
300.0f);
/* We want to displace the rectangle to the right by
100 points but want to keep the y position
untouched */
// CGAffineTransform transform = CGAffineTransformMakeTranslation(100.0f,
// 0.0f);
/* Scale the rectangle to half its size */
CGAffineTransform transform = CGAffineTransformMakeScale(0.5f, 0.5f);
/* Add the rectangle to the path */
CGPathAddRect(path,
&transform,
rectangle);
NSLog(@"transform=%@", NSStringFromCGAffineTransform(transform));
/* Add the rectangle to the path */
CGPathAddRect(path,
&transform,
rectangle);
/* Get the handle to the current context */
CGContextRef currentContext = UIGraphicsGetCurrentContext();
/* Add the path to the context */
CGContextAddPath(currentContext, path);
/* Set the fill color to cornflower blue */
[[UIColor colorWithRed:0.20f
green:0.60f
blue:0.80f
alpha:1.0f] setFill]; /* Set the stroke color to brown */
[[UIColor brownColor] setStroke];
/* Set the line width (for the stroke) to 5 */
CGContextSetLineWidth(currentContext,5.0f);
/* Stroke and fill the path on the context */
CGContextDrawPath(currentContext,kCGPathFillStroke);
/* Dispose of the path */
CGPathRelease(path);
}
运行:
2014-08-06 15:53:11.857 cookbook7_20[713:a0b] transform=[0.5, 0, 0, 0.5, 0, 0]
- (void)drawRect:(CGRect)rect{
/* Create the path first. Just the path handle. */
CGMutablePathRef path = CGPathCreateMutable();
/* Here are our rectangle boundaries */
CGRect rectangle = CGRectMake(10.0f,
30.0f,
200.0f,
300.0f);
/* Add the rectangle to the path */
CGPathAddRect(path,
NULL,
rectangle);
/* Get the handle to the current context */
CGContextRef currentContext = UIGraphicsGetCurrentContext();
/* Scale everything drawn on the current
graphics context to half its size */
CGContextScaleCTM(currentContext,
0.5f,
0.5f);
/* Add the path to the context */
CGContextAddPath(currentContext,
path);
/* Set the fill color to cornflower blue */
[[UIColor colorWithRed:0.20f
green:0.60f
blue:0.80f
alpha:1.0f] setFill]; /* Set the stroke color to brown */
[[UIColor brownColor] setStroke];
/* Set the line width (for the stroke) to 5 */
CGContextSetLineWidth(currentContext,
5.0f);
/* Stroke and fill the path on the context */
CGContextDrawPath(currentContext,
kCGPathFillStroke);
/* Dispose of the path */
CGPathRelease(path);
}
运行:
20.13. Rotating Shapes Drawn on Graphic Contexts
CGAffineTransformMakeRotation
- (void)drawRect:(CGRect)rect{
/* Create the path first. Just the path handle. */
CGMutablePathRef path = CGPathCreateMutable();
/* Here are our rectangle boundaries */
CGRect rectangle = CGRectMake(10.0f,
30.0f,
200.0f,
300.0f);
/* Rotate the rectangle 45 degrees clockwise */
CGAffineTransform transform =
CGAffineTransformMakeRotation((45.0f * M_PI) / 180.0f);
/* Add the rectangle to the path */
CGPathAddRect(path,
&transform,
rectangle);
NSLog(@"transform=%@", NSStringFromCGAffineTransform(transform));
/* Add the rectangle to the path */
CGPathAddRect(path,
&transform,
rectangle);
/* Get the handle to the current context */
CGContextRef currentContext = UIGraphicsGetCurrentContext();
/* Add the path to the context */
CGContextAddPath(currentContext, path);
/* Set the fill color to cornflower blue */
[[UIColor colorWithRed:0.20f
green:0.60f
blue:0.80f
alpha:1.0f] setFill]; /* Set the stroke color to brown */
[[UIColor brownColor] setStroke];
/* Set the line width (for the stroke) to 5 */
CGContextSetLineWidth(currentContext,5.0f);
/* Stroke and fill the path on the context */
CGContextDrawPath(currentContext,kCGPathFillStroke);
/* Dispose of the path */
CGPathRelease(path);
}
运行:
2014-08-06 16:01:13.445 cookbook7_20[732:a0b] transform=[0.70710677, 0.70710677, -0.70710677, 0.70710677, 0, 0]
20.14. Animating and Moving Views
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// [self testresizableImageWithCapInsets];
// [self testdraw];
UIImage *xcodeImage = [UIImage imageNamed:@"Xcode"];
self.xcodeImageView = [[UIImageView alloc]
initWithImage:xcodeImage];
/* Just set the size to make the image smaller */
[self.xcodeImageView setFrame:CGRectMake(0.0f,
30.0f,
100.0f,
100.0f)];
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.xcodeImageView];
}
- (void) viewDidAppear:(BOOL)paramAnimated{
[super viewDidAppear:paramAnimated];
/* Start from top left corner */
[self.xcodeImageView setFrame:CGRectMake(0.0f,
30.0f,
100.0f,
100.0f)];
[UIView beginAnimations:@"xcodeImageViewAnimation" context:(__bridge void *)self.xcodeImageView];
/* 5 seconds animation */
[UIView setAnimationDuration:5.0f];
/* Receive animation delegates */
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(imageViewDidStop:finished:context:)];
CGRect endRect;
endRect.origin.x = self.view.bounds.size.width - 100;
endRect.origin.y = self.view.bounds.size.height - 100;
endRect.size = CGSizeMake(100.0f, 100.0f);
/* End at the bottom right corner */
[self.xcodeImageView setFrame:endRect];
[UIView commitAnimations];
}
- (void)imageViewDidStop:(NSString *)paramAnimationID
finished:(NSNumber *)paramFinished
context:(void *)paramContext{
NSLog(@"Animation finished.");
NSLog(@"Animation ID = %@", paramAnimationID);
UIImageView *contextImageView = (__bridge UIImageView *)paramContext;
NSLog(@"Image View = %@", contextImageView);
}
运行:
2014-08-06 17:10:46.763 cookbook7_20[979:a0b] Animation finished.
2014-08-06 17:10:46.764 cookbook7_20[979:a0b] Animation ID = xcodeImageViewAnimation
2014-08-06 17:10:46.766 cookbook7_20[979:a0b] Image View = <UIImageView: 0x89673e0; frame = (220 380; 100 100); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8965440>> - (null)
图片从左上角慢慢移动到右下角。
不知道书上为什么没介绍这个,感觉更喜欢用下面这个
- (void) viewDidAppear:(BOOL)paramAnimated{
[super viewDidAppear:paramAnimated];
/* Start from top left corner */
[self.xcodeImageView setFrame:CGRectMake(0.0f,
30.0f,
100.0f,
100.0f)];
[UIView animateWithDuration:5.0f animations:^{
CGRect endRect;
endRect.origin.x = self.view.bounds.size.width - 100;
endRect.origin.y = self.view.bounds.size.height - 100;
endRect.size = CGSizeMake(100.0f, 100.0f);
/* End at the bottom right corner */
[self.xcodeImageView setFrame:endRect];
} completion:^(BOOL finished) {
NSLog(@"finished");
}];
}
效果一样
20.15. Animating and Scaling Views
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIImage *xcodeImage = [UIImage imageNamed:@"Xcode"];
self.xcodeImageView = [[UIImageView alloc]
initWithImage:xcodeImage];
/* Just set the size to make the image smaller */
[self.xcodeImageView setFrame:CGRectMake(0.0f,
30.0f,
100.0f,
100.0f)];
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.xcodeImageView];
}
#if 1
- (void) viewDidAppear:(BOOL)paramAnimated{
[super viewDidAppear:paramAnimated];
/* Place the image view at the center of the view of this view controller */
self.xcodeImageView.center = self.view.center;
/* Make sure no translation is applied to this image view */
self.xcodeImageView.transform = CGAffineTransformIdentity;
/* Begin the animation */
[UIView beginAnimations:nil
context:NULL];
/* Make the animation 5 seconds long */
[UIView setAnimationDuration:5.0f];
/* Make the image view twice as large in
width and height */
self.xcodeImageView.transform = CGAffineTransformMakeScale(2.0f,
2.0f);
/* Commit the animation */
[UIView commitAnimations];
}
#else //或者这个也行
- (void) viewDidAppear:(BOOL)paramAnimated{
[super viewDidAppear:paramAnimated];
/* Place the image view at the center of the view of this view controller */
self.xcodeImageView.center = self.view.center;
/* Make sure no translation is applied to this image view */
self.xcodeImageView.transform = CGAffineTransformIdentity;
[UIView animateWithDuration:5.0f animations:^{
self.xcodeImageView.transform = CGAffineTransformMakeScale(2.0f, 2.0f);
}];
}
#endif
20.16. Animating and Rotating Views
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIImage *xcodeImage = [UIImage imageNamed:@"Xcode"];
self.xcodeImageView = [[UIImageView alloc]
initWithImage:xcodeImage];
/* Just set the size to make the image smaller */
[self.xcodeImageView setFrame:CGRectMake(0.0f,
30.0f,
100.0f,
100.0f)];
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.xcodeImageView];
}
- (void) viewDidAppear:(BOOL)paramAnimated{
[super viewDidAppear:paramAnimated];
self.xcodeImageView.center = self.view.center;
/* Begin the animation */
[UIView beginAnimations:@"clockwiseAnimation"
context:NULL];
/* Make the animation 5 seconds long */
[UIView setAnimationDuration:5.0f];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector: @selector(clockwiseRotationStopped:finished:context:)];
/* Rotate the image view 90 degrees */
self.xcodeImageView.transform = CGAffineTransformMakeRotation((90.0f * M_PI) / 180.0f);
/* Commit the animation */
[UIView commitAnimations];
}
- (void)clockwiseRotationStopped:(NSString *)paramAnimationID
finished:(NSNumber *)paramFinished
context:(void *)paramContext{
[UIView beginAnimations:@"counterclockwiseAnimation"
context:NULL];
/* 5 seconds long */
[UIView setAnimationDuration:5.0f];
/* Back to original rotation */
self.xcodeImageView.transform = CGAffineTransformIdentity;
[UIView commitAnimations];
}
运行:
先顺时针旋转90度后,在逆时针旋转90度
20.17. Capturing a Screenshot of Your View into an Image
抓图
- (void) viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
/* Capture the screenshot */
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, YES, 0.0f);
//提示没这个方法drawViewHierarchyInRect:-_-!
if ([self.view drawViewHierarchyInRect:self.view.bounds]){
NSLog(@"Successfully draw the screenshot.");
} else {
NSLog(@"Failed to draw the screenshot.");
}
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
/* Save it to disk */
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSURL *documentsFolder = [fileManager URLForDirectory:NSDocumentDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
error:nil];
NSURL *screenshotUrl = [documentsFolder URLByAppendingPathComponent:@"screenshot.png"];
NSData *screenshotData = UIImagePNGRepresentation(screenshot);
if ([screenshotData writeToURL:screenshotUrl atomically:YES]){
NSLog(@"Successfully saved screenshot to %@", screenshotUrl);
} else {
NSLog(@"Failed to save screenshot.");
}
}
提示没这个方法drawViewHierarchyInRect:
用例执行不了-_-!