图形图像及动画 iOS 控制器 iOS 多媒体 图形图像及动画 内容概述 字体和颜色 绘制文本 绘制图片 划线 画矩形 移动动画 缩放动画 旋转动画 我们看到很多应用程序和游戏有漂亮的画面和动画效果,这些都离不开图形图像和动画编程。iOS SDK 对图形图像和动画的支持包括在如下的框架中: Quartz,该框架是一个强大的2D图形引擎,用来创建矢量图,位图和PDF等格式的内容。 UIKit,UIKit使用Quartz来创建,主要提供系统上层UI界面,如窗口、按钮和标签等。 Core Animation,该框架提供了视图的动画效果,如移动、旋转和缩放等。 OpenGL ES,该框架提供了专门针对移动设备的3D图形引擎。 UIKit框架的内容在前面章节用户界面中已经讲述,本章重点讲述如何使用Quartz框架绘图,如何使用Core Animation框架创建动画效果以及字体和颜色的应用。 20.1 字体和颜色 为显示的文本内容设置合适的字体和颜色,对于文本内容的展示效果至关重要。在iOS SDK的UIKit框架中提供了字体和颜色的支持。字体类是UIFont颜色类是UIColor。 我们可以使用UIFont的+ (UIFont )fontWithName:(NSString )fontName size:(CGFloat)fontSize方法创建一个新字体,可以使用+ (UIFont )systemFontOfSize:(CGFloat)fontSize方法创建指定大小的系统字体,也可以使用+ (UIFont )boldSystemFontOfSize:(CGFloat)fontSize方法创建粗体系统字体。 使用UIFont的+ (NSArray )familyNames方法获得字体家族数组,也可以使用+ (NSArray )fontNamesForFamilyName:(NSString *)familyName方法获得字体数组。 下面通过一个案例来演示字体的用法,创建步骤如下: 创建一个项目,在界面上添加两个按钮,和4个标签组件,在.h头文件中添加两个按钮的点击事件方法和4个标签的属性。 @interface AmakerViewController : UIViewController // 获得字体的属性 - (IBAction)get:(id)sender; // 显示系统支持的字体家族名称 - (IBAction)display:(id)sender; // 为标签设置字体,默认字体 @property (strong, nonatomic) IBOutlet UILabel *normalLabel; // 为标签设置字体,粗体字体 @property (strong, nonatomic) IBOutlet UILabel *boldLabel; // 为标签设置字体,斜体字体 @property (strong, nonatomic) IBOutlet UILabel *italicLabel; // 为标签设置字体,自定义字体 @property (strong, nonatomic) IBOutlet UILabel *customLabel; @end 在viewDidLoad方法中创建字体,并为标签设置字体。 - (void)viewDidLoad { [super viewDidLoad]; // 创建字体 UIFont *f1 = [UIFont fontWithName:@"OriyaSangamMN-Bold" size:20]; self.customLabel.font = f1; // 使用系统字体 UIFont *font1 = [UIFont systemFontOfSize:20]; self.normalLabel.font = font1; // 使用系统加粗字体 UIFont *font2 = [UIFont boldSystemFontOfSize:20]; self.boldLabel.font = font2; // 使用系统字体加斜字体 UIFont *font3 = [UIFont italicSystemFontOfSize:20]; self.italicLabel.font = font3; } 在display方法中获得字体家族数组和字体数组。 - (IBAction)display:(id)sender { // 遍历系统字体家族 NSArray *family = [UIFont familyNames]; for(NSString *familyName in family){ NSLog(@"FamilyName=%@",familyName); NSArray *fontNames = [UIFont fontNamesForFamilyName:familyName]; for(NSString *fontName in fontNames){ NSLog(@"\tFontName=%@",fontName); } } } 在get方法中获得字体属性。 - (IBAction)get:(id)sender { // 获得字体属性 UIFont *f1 = [UIFont fontWithName:@"GillSans-Light" size:20]; NSString *familyName1 = f1.familyName; NSString *fontName1 = f1.fontName; NSLog(@"FamilyName=%@",familyName1); NSLog(@"FontName=%@",fontName1); } 项目运行结果如下所示。 可以用一个UIColor对象来定义文字的色彩。UIColor这个类提供了许多不同的方法,可以很轻松地调出任何颜色。你可以用静态方法来创建 颜色,这样它们会在停止使用后被释放。可以用灰度值、色相或者RGB复合值等多种形式来创建颜色。要创建一个简单的RGB色彩,可以指定一组4个浮点值, 分别对应红、绿、蓝和alpha值(透明度),取值均在0.0~1.0之间。 UIColor类还支持许多静态方法,可以创建系统颜色,这些颜色都经过iPhone的校正,以达到尽可能准确的地步。这些方法如下所示。 + (UIColor *)blackColor; // 0.0 白色 + (UIColor *)darkGrayColor; // 0.333 白色 + (UIColor *)lightGrayColor; // 0.667 白色 + (UIColor *)whiteColor; // 1.0 白色 + (UIColor *)grayColor; // 0.5 白色 + (UIColor *)redColor; // 1.0, 0.0, 0.0 RGB + (UIColor *)greenColor; // 0.0, 1.0, 0.0 RGB + (UIColor *)blueColor; // 0.0, 0.0, 1.0 RGB + (UIColor *)cyanColor; // 0.0, 1.0, 1.0 RGB + (UIColor *)yellowColor; // 1.0, 1.0, 0.0 RGB + (UIColor *)magentaColor; // 1.0, 0.0, 1.0 RGB + (UIColor *)orangeColor; // 1.0, 0.5, 0.0 RGB + (UIColor *)purpleColor; // 0.5, 0.0, 0.5 RGB + (UIColor *)brownColor; // 0.6, 0.4, 0.2 RGB + (UIColor *)clearColor; // 0.0 白色, 0.0 alpha 另外,可以使用RGB三原色和透明度来定义颜色,+ colorWithRed:green:blue:alpha:。如果你有一张背景图片想转换为UIColor可以使用+ colorWithPatternImage:方法。如果我们有一个16进制的颜色值,想转换为UIColor,要先将16进制转换为10进制,然后使用该值除以255.0得到RGB值。例如,#F6F6F6 为一个 16 进制表示的RPG颜色,所以,需要先转换成 10进制,其中 F6 - 240,F6 - 240 ,F6 - 240 之后,使用 UIColor *testColor1= [UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1];代码获得UIColor对象。下面通过一个案例来演示UIColor的用法。该案例使用一张图片为当前视图指定背景图片,并为两个标签指定颜色。实现步骤如下所示。 创建一个项目,在界面上添加两个标签,在.h头文件中添加两个标签的属性。 @interface AmakerViewController : UIViewController // 标签1 @property (strong, nonatomic) IBOutlet UILabel *label1; // 标签2 @property (strong, nonatomic) IBOutlet UILabel *label2; @end 在viewDidLoad方法中为视图指定背景色,并为两个标签指定文字颜色。 - (void)viewDidLoad { [super viewDidLoad]; // 使用图片背景 UIColor *bgColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"test.jpeg"]]; // 为当前视图指定背景 self.view.backgroundColor = bgColor; // 使用RGB创建颜色 UIColor *labelColor1 = [UIColor colorWithRed:0.2 green:0.3 blue:0.2 alpha:1]; // 为标签指定颜色 self.label1.textColor = labelColor1; // 使用红色 UIColor *labelColor2 = [UIColor redColor]; // 为标签指定颜色 self.label2.textColor = labelColor2; } 运行程序结果如下所示。 20.2 绘制文本 可以使用NSString的- (CGSize)drawAtPoint:(CGPoint)point withFont:(UIFont )font方法使用某种字体在某个点绘制文本,也可以使用- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont )font方法使用某种字体在某个矩形框中绘制文本。下面通过一个案例来演示如何绘制文本。该案例自定义了一个视图,在该视图的drawRect方法中绘制文本。实现步骤如下: 创建一个项目。 自定义一个View继承UIView,并在drawRect方法中绘制文本。 - (void)drawRect:(CGRect)rect { // 要绘制的文字 NSString *str = @"《iOS 应用开发详解》"; // 绘制在点(20,20)使用字体大小24 [str drawAtPoint:CGPointMake(20, 20) withFont:[UIFont systemFontOfSize:24]]; // 在矩形中绘制 [str drawInRect:CGRectMake(20, 50, 300, 200) withFont:[UIFont systemFontOfSize:26]]; } 将xib文件中的view类指定为自定义的view。 程序运行结果如下所示。 20.3 绘制图片 绘制图片和绘制文本类似,可以在某个点绘制,也可以在某个矩形中绘制。使用的方法是- (void)drawAtPoint:(CGPoint)point和- (void)drawInRect:(CGRect)rect方法。下面通过一个案例演示如何绘制图片。实现步骤如下: 创建一个项目。 自定义一个view,继承UIView,在drawRect方法中实现绘制图片。 - (void)drawRect:(CGRect)rect { // 实例化一个UIImage对象 UIImage *image = [UIImage imageNamed:@"iphone.jpg"]; // 在(20,20)点绘制图片 [image drawAtPoint:CGPointMake(20, 20)]; // 在矩形中绘制图片 [image drawInRect:CGRectMake(20, 200, 300, 200)]; } 程序运行结果如下所示。 20.4 画线 在iOS中绘制直线, 使用到一个绘制环境对象CGContextRef,该对象可以使用UIGraphicsGetCurrentContext()函数获得。绘制直线和矩形等形状会使用一组以CGContextXXX打头的函数来完成,例如,CGContextSetLineWidth()设置线宽、CGContextSetStrokeColorWithColor()设置颜色、CGContextMoveToPoint()移动到某个点等。下面通过一个案例来演示如何实现划线,该案例可以实现在手指划过的起始点和结束点之间画一条直线。实现步骤如下: 创建一个项目。 自定义一个视图类view,该类继承UIView,在头文件中定义两个点。 #import <UIKit/UIKit.h> @interface MyView : UIView // 起始点 @property(nonatomic)CGPoint startPoint; // 结束点 @property(nonatomic)CGPoint endPoint; @end 在view的drawRect方法中,获得绘制上下文、设置线宽、绘制颜色、定位起始点和结束点并进行绘制。 - (void)drawRect:(CGRect)rect { // 获得上下文 CGContextRef context =UIGraphicsGetCurrentContext(); // 设置线宽 CGContextSetLineWidth(context, 2); // 设置绘制颜色 CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); // 移动到指定的点 CGContextMoveToPoint(context, self.startPoint.x, self.startPoint.y); // 添加一条线到指定点 CGContextAddLineToPoint(context, self.endPoint.x, self.endPoint.y); // 绘制 CGContextStrokePath(context); } 覆盖touchesBegan、touchesMoved和touchesEnded方法。获得起始点和结束点。 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ // 获得当前点 UITouch *touch = [touches anyObject]; // 初始化起始点和结束点 self.startPoint = [touch locationInView:self]; self.endPoint = [touch locationInView:self]; // 触发绘制 [self setNeedsDisplay]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ // 获得当前点 UITouch *touch = [touches anyObject]; // 获得结束点 self.endPoint = [touch locationInView:self]; // 触发绘制 [self setNeedsDisplay]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ // 获得当前点 UITouch *touch = [touches anyObject]; // 获得结束点 self.endPoint = [touch locationInView:self]; // 触发绘制 [self setNeedsDisplay]; } 程序运行结果如下所示。 20.5 绘制矩形 绘制矩形和绘制直线类似,使用UIGraphicsGetCurrentContext()函数获得绘制上下文、设置绘制颜色、创建矩形、添加矩形CGContextAddRect(context, r)并且绘制矩形CGContextDrawPath(context, kCGPathFill)。 下面的案例可以手动的在界面上动态绘制矩形,实现步骤如下。 创建一个项目。 自定义一个视图类view,该类继承UIView,在头文件中定义两个点。 #import <UIKit/UIKit.h> @interface MyView : UIView // 起始点 @property(nonatomic)CGPoint startPoint; // 结束点 @property(nonatomic)CGPoint endPoint; @end 在view的drawRect方法中,获得绘制上下文、设置线宽、绘制颜色、定位起始点和结束点并进行绘制。 - (void)drawRect:(CGRect)rect { // 获得上下文 CGContextRef context = UIGraphicsGetCurrentContext(); // 设置绘制颜色 CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor); // 创建矩形 CGRect r = CGRectMake(self.startPoint.x>self.endPoint.x?self.endPoint.x:self.startPoint.x, self.startPoint.y>self.endPoint.y?self.endPoint.y:self.startPoint.y, fabsf(self.startPoint.x-self.endPoint.x), fabsf(self.startPoint.y-self.endPoint.y)); // 添加矩形 CGContextAddRect(context, r); // 绘制矩形 CGContextDrawPath(context, kCGPathFill); } 覆盖touchesBegan、touchesMoved和touchesEnded方法。获得起始点和结束点。 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ // 获得当前点 UITouch *touch = [touches anyObject]; // 初始化起始点和结束点 self.startPoint = [touch locationInView:self]; self.endPoint = [touch locationInView:self]; // 触发绘制 [self setNeedsDisplay]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ // 获得当前点 UITouch *touch = [touches anyObject]; // 获得结束点 self.endPoint = [touch locationInView:self]; // 触发绘制 [self setNeedsDisplay]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ // 获得当前点 UITouch *touch = [touches anyObject]; // 获得结束点 self.endPoint = [touch locationInView:self]; // 触发绘制 [self setNeedsDisplay]; } 程序运行结果如下所示。 20.6 移动动画 UIView中定义了一组静态方法,来实现视图的动画效果,例如,beginAnimations开始动画、setAnimationDuration设置动画持续时间、commitAnimations提交动画等。 下面通过一个按钮来实现移动动画,移动动画除了使用上述方法外,要改变视图的重要属性是frame属性,即更改视图的位置信息。该案例在界面上添加一个图片视图和一个按钮,当点击按钮是是图片从左上角移动到右下角。实现步骤如下: 创建一个项目,在界面上添加一个图片和一个按钮,并添加图片的属性和按钮的点击事件方法。 #import <UIKit/UIKit.h> @interface AmakerViewController : UIViewController // 图片属性 @property (strong, nonatomic) IBOutlet UIImageView *myImage; // 移动事件方法 - (IBAction)move:(id)sender; @end 在move事件方法中实现动画效果。 - (IBAction)move:(id)sender { // 开始动画 [UIView beginAnimations:@"myAnimation" context:(\_\_bridge void *)self.myImage]; // 设置动画持续时间 [UIView setAnimationDuration:5.0f]; // 重新设置图片frame属性 [self.myImage setFrame:CGRectMake(200.0f, 350.0f,100.0f,100.0f)]; // 提交动画 [UIView commitAnimations]; } 程序运行效果如下所示。 20.7 缩放动画 除了移动动画之外,我们还可以实现视图的缩放和旋转。本节我们来看如何实现视图的缩放,视图的缩放使用到另外一个类CGAffineTransform,即射频转换类,使用该类可以实现视图的缩放和旋转。 下面通过一个案例来演示如何实现视图的缩放。步骤如下: 创建一个项目在界面上添加一个按钮和一个图片视图。声明图片属性和按钮单击事件方法和缩放比例属性。 #import <UIKit/UIKit.h> @interface AmakerViewController : UIViewController // 图片属性 @property (strong, nonatomic) IBOutlet UIImageView *myImage; // 缩放方法 - (IBAction)scale:(id)sender; //缩放比例大小 @property(nonatomic)float scale; @end 在scale方法中实现缩放,这里使用CGAffineTransform CGAffineTransformMakeScale (CGFloat sx,CGFloat sy);方法指定x、y轴的缩放比例。 - (IBAction)scale:(id)sender { // 更改缩放比例 self.scale = self.scale==2.0?0.5:2.0; // 开始动画 [UIView beginAnimations:nil context:nil]; // 设置持续时间 [UIView setAnimationDuration:3]; // 设置动画效果(渐进渐出) [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; // 设置缩放比例 CGAffineTransform scaleTrans = CGAffineTransformMakeScale(self.scale, self.scale); // 为图片设置转换 self.myImage.transform = scaleTrans; // 提交动画 [UIView commitAnimations]; } 程序运行结果如下所示。 20.8 旋转动画 除了移动动画、缩放动画之外,我们还可以实现视图的旋转。本节我们来看如何实现视图的旋转,视图的旋转使用到另外一个类CGAffineTransform,即射频转换类,使用该类可以实现视图的缩放和旋转。 下面通过一个案例来演示如何实现视图的旋转。步骤如下: 创建一个项目在界面上添加一个按钮和一个图片视图。声明图片属性和按钮单击事件方法。 #import <UIKit/UIKit.h> @interface AmakerViewController : UIViewController // 图片属性 @property (strong, nonatomic) IBOutlet UIImageView *myImage; // 缩放方法 - (IBAction) rotate:(id)sender; @end 在rotate方法中实现旋转,这里使用CGAffineTransformMakeRotation(180 * M_PI / 180);方法设置旋转弧度。 - (IBAction) rotate:(id)sender { // 开始动画 [UIView beginAnimations:nil context:nil]; // 设置持续时间 [UIView setAnimationDuration:3]; // 设置动画效果(渐进渐出) [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; // 设置旋转弧度 CGAffineTransform rotationTrans = CGAffineTransformMakeRotation(180 * M\_PI / 180); // 为图片设置转换 self.myImage.transform = rotationTrans; // 提交动画 [UIView commitAnimations]; } 程序运行结果如下所示。 iOS 控制器 iOS 多媒体