Core Graphics 101: 阴影和光泽效果

来源:互联网 发布:华安股票交易软件 编辑:程序博客网 时间:2024/05/01 11:43
Custom draw the header of this table!
个性化绘制table view的header!

这是结合实例代码讲解Core Graphics API的教程系列的第二部分内容!

在第一部分教程中,我们通过制作美观的table view cell背景,讲解了如何绘制线条,矩形和颜色渐变效果。

在这篇教程中,我们将继续个性化table view的header。同时,我们将巩固一些已经学会的知识,进一步学习阴影和光泽效果!

如果你还没有上篇教程的例子代码,可以在这里下载。

开始

个性化我们的table view的下一步是美化table view 的header。开始前,让我们先按照之前的方式做好初步设置 – 制作一个红色的view,设置为header的view。

确保”Groups & Files”下面的”Classes”分组被选中,前往菜单的“FileNew File…”,选择 iOSCocoa Touch Class, Objective-C class,确保”Subclass of UIView”选项被选中,然后点击下一步。命名文件为 ”CustomHeader.m”,确保 ”Also create CustomHeader.h”被选中,然后点击 ”Finish”。

切换到CustomHeader.m文件,取消drawRect方法的注释,用以下代码替换掉原来的内容:

CGContextRef context = UIGraphicsGetCurrentContext();CGColorRef redColor = [UIColor colorWithRed:1.0 green:0.0     blue:0.0 alpha:1.0].CGColor; CGContextSetFillColorWithColor(context, redColor);CGContextFillRect(context, self.bounds);

你应该已经对这些操作很熟悉了,因为我们之前做过!

现在让我们设置它为header的view吧。切换到RootViewController.m文件,根据以下代码做修改:

// In import section#import "CustomHeader.h"// Add new methods- (UIView *) tableView:(UITableView *)tableView     viewForHeaderInSection:(NSInteger)section {    CustomHeader *header = [[[CustomHeader alloc] init] autorelease];            return header;}-(CGFloat) tableView:(UITableView *)tableView     heightForHeaderInSection:(NSInteger)section {    return 50;}

实现viewForHeaderInSection方法就可以替换掉table view的header view。我们还需要实现heightForHeaderInSection方法来让table view知道header的高度。

编译运行工程,如果一切运行正常,你将看到以下画面:

Placeholders for Custom Header

很好 – 现在我们来用漂亮的view去填充这个区域吧!

目标

先刷新下内存空间。以下是我们想要的header view的放大效果:

Zoomed in view of Header

注意以下对上述效果的描述:

  • 蓝色区域是从浅蓝色到深蓝色的渐变。
  • 蓝色区域的顶部有光泽的效果。
  • 在蓝色区域的边界处有深蓝色的边。
  • 在方框的底部有微小的阴影效果。
  • 页面的顶部区域已经绘制好了,引入到了顶部cell。
  • Table view controller需要为每个view设置颜色和label标签。

以上内容是对上篇教程和Custom UIViews教程的很好复习,但是我们会在接下来讲解一些新内容!

开始动手

首先要做的是一些基本设置。我们需要让table view可以设置header的颜色和显示一些文本,然后设置一些矩形以便我们在上面绘制(比如header bar还有页面的下拉效果)。

现在我们开始动手。根据以下代码对CustomHeader.h文件进行修改:

// Inside @interfaceUILabel *_titleLabel;UIColor *_lightColor;UIColor *_darkColor;CGRect _coloredBoxRect;CGRect _paperRect;// After @interface@property (retain) UILabel *titleLabel;@property (retain) UIColor *lightColor;@property (retain) UIColor *darkColor;

然后根据以下代码内容对CustomHeader.m文件进行修改:

// In import section#import "Common.h"// After @implementation@synthesize titleLabel = _titleLabel;@synthesize lightColor = _lightColor;@synthesize darkColor = _darkColor;// Add new methods- (id)init {    if ((self = [super init])) {        self.backgroundColor = [UIColor clearColor];        self.opaque = NO;        self.titleLabel = [[[UILabel alloc] init] autorelease];        _titleLabel.textAlignment = UITextAlignmentCenter;        _titleLabel.opaque = NO;        _titleLabel.backgroundColor = [UIColor clearColor];        _titleLabel.font = [UIFont boldSystemFontOfSize:20.0];        _titleLabel.textColor = [UIColor whiteColor];        _titleLabel.shadowColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];        _titleLabel.shadowOffset = CGSizeMake(0, -1);        [self addSubview:_titleLabel];        self.lightColor = [UIColor colorWithRed:105.0f/255.0f green:179.0f/255.0f             blue:216.0f/255.0f alpha:1.0];        self.darkColor = [UIColor colorWithRed:21.0/255.0 green:92.0/255.0             blue:136.0/255.0 alpha:1.0];            }    return self;}-(void) layoutSubviews {     CGFloat coloredBoxMargin = 6.0;    CGFloat coloredBoxHeight = 40.0;    _coloredBoxRect = CGRectMake(coloredBoxMargin,                                  coloredBoxMargin,                                  self.bounds.size.width-coloredBoxMargin*2,                                  coloredBoxHeight);     CGFloat paperMargin = 9.0;    _paperRect = CGRectMake(paperMargin,                             CGRectGetMaxY(_coloredBoxRect),                             self.bounds.size.width-paperMargin*2,                             self.bounds.size.height-CGRectGetMaxY(_coloredBoxRect));     _titleLabel.frame = _coloredBoxRect; }// Replace drawRect with the following- (void)drawRect:(CGRect)rect {     CGContextRef context = UIGraphicsGetCurrentContext();     CGColorRef redColor = [UIColor colorWithRed:1.0 green:0.0         blue:0.0 alpha:1.0].CGColor;    CGColorRef greenColor = [UIColor colorWithRed:0.0 green:1.0         blue:0.0 alpha:1.0].CGColor;     CGContextSetFillColorWithColor(context, redColor);    CGContextFillRect(context, _coloredBoxRect);     CGContextSetFillColorWithColor(context, greenColor);    CGContextFillRect(context, _paperRect);}// Inside dealloc[_titleLabel release];_titleLabel = nil;[_lightColor release];_lightColor = nil;[_darkColor release];_darkColor = nil;

在之前的教程基础上,上面的内容你都应该觉得很熟悉。我们快速过一遍。

在init方法中,我们用一些基本的数值建立了label标签。注意到我们给文本的顶部设置了一块微小的阴影,让它看起来像锯齿状。原因:如果光线在顶部,然后有些锯齿效果,就会在上部区域有阴影了。

我们也要确保视图是透明的,因为我们想让背景可以露出来一点。

当我们的view改变大小时就会调用layoutSubviews方法。这里是我们要添加代码去计算需要绘制颜色方框的矩形尺寸,以及绘制页面位置的地方。每一项都是很直接的计算过程。

最后,我们在drawRect函数中使用不同的颜色去填充每一个方框区域,以确保我们计算正确。

使用以下代码对RootViewController.m文件进行修改:

// Inside tableView:viewForHeaderInSection, before returnheader.titleLabel.text = [self tableView:tableView titleForHeaderInSection:section];

编译运行程序,然后如果运作正常,你会看到以下画面:
Header colored with subrects to draw

我们又离目标更进一步了!正如你看到的,用颜色填充矩形是一个方便的调试工具!

绘制阴影

让我们从基础开始讲解绘制的原理吧。我们会先绘制一个页面,然后是阴影,最后给方框盒子填充颜色。

绘制页面区域很简单 – 我们只要给方框填充上白色。

但是我们怎么去绘制阴影?好的,在Core Graphics里面,绘制阴影,你只需要调用一个函数去启用阴影绘制功能,然后绘制轨迹。根据你设定好的参数,阴影将被绘制在轨迹下面 – 这里不用管轨迹的形状!

让我们看看这是怎么工作的。使用以下代码,替换掉drawRect的方法:

CGContextRef context = UIGraphicsGetCurrentContext();    CGColorRef whiteColor = [UIColor colorWithRed:1.0 green:1.0     blue:1.0 alpha:1.0].CGColor;CGColorRef lightColor = _lightColor.CGColor;CGColorRef darkColor = _darkColor.CGColor;CGColorRef shadowColor = [UIColor colorWithRed:0.2 green:0.2     blue:0.2 alpha:0.5].CGColor;    CGContextSetFillColorWithColor(context, whiteColor);CGContextFillRect(context, _paperRect);CGContextSaveGState(context);CGContextSetShadowWithColor(context, CGSizeMake(0, 2), 3.0, shadowColor);CGContextSetFillColorWithColor(context, lightColor);CGContextFillRect(context, _coloredBoxRect);CGContextRestoreGState(context);

完成颜色和页面方框的绘制(你现在应该能够理解了)后,我们调用 CGContextSetShadowWithColor函数去进行阴影绘制。

第一个参数是阴影绘制时的offset(偏移量)值。这里我们在当前的轨迹下面绘制了两个点。

接下来的参数是阴影的blur(模糊度)值。o的值将会是颜色较深的边,值越大,边的颜色会越柔和。我们把值设定为3,使边的颜色变得柔和。

最后我们来设定阴影的颜色。注意到我们使用了灰色,它的alpha值为0.5(半透明),这让阴影变得更加逼真。

建立好阴影后,我们使用浅颜色来填充上色了的盒子方框。给轨迹填充颜色的操作,会体现在阴影上面。

最后的修改 – 既然我们使用了提供给我们的颜色,那现在修改RootViewController.m文件去改变section 1的颜色:

// Inside tableView:viewForHeaderInSection, before return statementif (section == 1) {    header.lightColor = [UIColor colorWithRed:147.0/255.0 green:105.0/255.0         blue:216.0/255.0 alpha:1.0];    header.darkColor = [UIColor colorWithRed:72.0/255.0 green:22.0/255.0         blue:137.0/255.0 alpha:1.0];}

编译运行工程,你将看到以下画面:
Headers with Shadow

Wow – 看起来已经相当漂亮了!现在让我们用颜色渐变,光泽效果对它去做进一步的修饰吧。

添加光泽效果

在Core Graphics中添加光泽效果到按钮上面,操作会相当复杂 – 如果你感受到了难度,看看 Matt Gallagher和 Michael Heyeck在这方面的突出贡献吧。

以我的看法,你可以通过使用一个渐变的alpha mask, 获得一种相当美观和接近的光泽效果,这会更加容易理解和编写代码,我们接下来会实现它。

下面的代码我们接下来还会用到,现在把代码添加到”Common.h”文件中:

void drawGlossAndGradient(CGContextRef context, CGRect rect, CGColorRef startColor,     CGColorRef endColor);

添加以下代码到Common.m文件中:

void drawGlossAndGradient(CGContextRef context, CGRect rect, CGColorRef startColor,     CGColorRef endColor) {     drawLinearGradient(context, rect, startColor, endColor);     CGColorRef glossColor1 = [UIColor colorWithRed:1.0 green:1.0         blue:1.0 alpha:0.35].CGColor;    CGColorRef glossColor2 = [UIColor colorWithRed:1.0 green:1.0         blue:1.0 alpha:0.1].CGColor;     CGRect topHalf = CGRectMake(rect.origin.x, rect.origin.y,         rect.size.width, rect.size.height/2);     drawLinearGradient(context, topHalf, glossColor1, glossColor2)}
好的,以上的代码负责在矩形上实现颜色渐变效果,然后添加光泽效果到顶部中间。

绘制渐变效果,我们调用之前写好的代码。

然后绘制光泽效果,我们只需要在它上面绘制另一层渐变效果,从相当透明(0.35alpha值的白色)到非常透明(0.1alpha值的白色)。

相当简单吧?我们把代码添加进去看下效果。回到CustomHeader.m文件,然后添加以下代码到drawRect:函数的底部:

drawGlossAndGradient(context, _coloredBoxRect, lightColor, darkColor);  // Draw strokeCGContextSetStrokeColorWithColor(context, darkColor);CGContextSetLineWidth(context, 1.0);    CGContextStrokeRect(context, rectFor1PxStroke(_coloredBoxRect));

这里我们使用新的程序代码,然后在方框周围绘制一个1像素点的深色笔画,正如在之前教程中学到的那样。编译运行程序,然后查看运行结果:
Headers with Gloss

我想现在已经相当不错了,你觉得呢?

现在还可以做什么?

这个是本教程的工程代码,你可以到这里下载。

到现在你应该很渴望去用Core Graphics绘制你自己的东西了 – 想想看你已经能做多少了!

还有个好消息 – 更多的内容将会在本教程系列中出现!在下一篇教程中,我们将用footer去完善好这个很酷的table view,你将在这个过程中学到如何使用Core Graphics去绘制弧线,并且做些收尾工作!

原创粉丝点击