教程说明
- 技术工具: iOS SDK
- 操作难度: 普通
- 执行时间: 30到60分钟
【51CTO译文】欢迎大家再次莅临本系列文章,我们将通过三篇指南帮助各位了解小型企业应用程序的开发过程。在今天的课程中,我们一起来看看AQGrid View是如何化腐朽为神奇,给应用项目带来精彩设计的。闲话少叙,这就开始!
教程概述
在本篇教程中,我将带大家一步步设计出如下图所示的应用程序视图。屏幕中的内容由网络所分割,可以用来显示公司提供的各项服务。AQGrid View是一款相当实用的开源组件,今天我们就来共同学习如何用它制作出精美的网格界面。
AQGrid View与UITableViewController相当类似,如果大家对于Table View比较熟悉,那么恭喜,这篇教程对你而言应该轻而易举。如果不熟悉也别担心,我仍然会一步步引导各位完成任务。
添加网格单元
那么,首先要做的是从GitHub网站下载AQGrid View,并将AQGrid View文件夹添加到项目当中。由于AQGrid View需要QuartzCore库才能运行,因此我们还要将其添加到项目中来。就这些,准备工作到此结束。
现在我们要做的是添加包含着各个标签详细信息的类。在项目中添加一个新文件,选择Cocoa Touch中的Objective-C Class选项,再点选NSObject模板。我们将其命名为GridViewCell。
在GridViewCell头文件中将继承对象变更为AQGridViewCell,这相当于网格视图组件中UITableViewCell的作用。另外,还要将图像视图与标签添加到上述头文件中。
- #import <UIKit/UIKit.h>
- #import "AQGridView.h"
- @interface GridViewCell : AQGridViewCell
- @property (nonatomic, retain) UIImageView * imageView;
- @property (nonatomic, retain) UILabel * captionLabel;
- @end
在GridViewCell.m执行文件中,我们要写入一套用于创建视图、图像视图以及多标签(以弥补初始状态下的单标签机制)功能的初始化方法。
- - (id) initWithFrame: (CGRect) frame reuseIdentifier: (NSString *) aReuseIdentifier
- {
- self = [super initWithFrame: frame reuseIdentifier: aReuseIdentifier];
- if ( self)
- {
- UIView* mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 160, 123)];
- [mainView setBackgroundColor:[UIColor clearColor]];
- UIImageView *frameImageView = [[UIImageView alloc] initWithFrame:CGRectMake(9, 4, 142, 117)];
- [frameImageView setImage:[UIImage imageNamed:@"tab-mask.png"]];
- self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(13, 8, 135, 84)];
- self.captionLabel = [[UILabel alloc] initWithFrame:CGRectMake(13, 92, 127, 21)];
- [captionLabel setFont:[UIFont systemFontOfSize:14]];
- [mainView addSubview:imageView];
- [mainView addSubview:frameImageView];
- [mainView addSubview:captionLabel];
- [self.contentView addSubview:mainView];
- }
- return self;
- }
该函数看起来与标准UITableViewCell中的init函数非常相近,而在本教程中二者惟一的不同在于,我们要在视图及单元中加入一些基本布局方案。最终结果将以双层图案的形式显示,一层是白色的边框、反衬出服务图像,另一层则用于描述服务本身。如果大家读到这里感到有些迷惑,不妨回到文章开头,相信最终效果图会让大家感到豁然开朗。
我们还要为选项卡配上说明用的标签。
以上各视图创建完成后,我们将其添加到UIView当中(以便于管理),再将UIView整体添加进单元本身。
创建网格控制器
接下来我们开始创建视图控制器,它的作用是管理网格委托及其数据源。添加一个新文件,使用Cocoa Touch中的Objective –C Class选项,并点选NSObject模板,将其命名为GridViewController。然后修改GridViewController.h文件,使其成为AQGridViewController的一个子类。另外我们还要添加几个域,用于容纳GridView自身以及网格中将要用到的服务项目列表。
- #import <UIKit/UIKit.h>
- #import "AQGridView.h"
- @interface GridViewController : UIViewController <AQGridViewDelegate, AQGridViewDataSource>
- @property (nonatomic, retain) IBOutlet AQGridView * gridView;
- @property (nonatomic, retain) NSArray * services;
- @end
添加ViewDidLoad方法,在这里我们将对视图及数据进行配置。不过我们首先来配置GridView。
- @synthesize gridView, services;
- - (void) viewDidLoad
- {
- [super viewDidLoad];
- self.gridView = [[AQGridView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
- self.gridView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
- self.gridView.autoresizesSubviews = YES;
- self.gridView.delegate = self;
- self.gridView.dataSource = self;
- [self.view addSubview:gridView];
- [self.gridView reloadData];
- }
将委托生成器添加进来,接着初始化网格并加以配置。我们还必须确保当前类GridViewController已经被正确指定为GridView的委托与数据源。把网格添加到当前视图中并重新载入数据,保证整个流程从头开始按顺序进行。
现在我们需要执行上述方法,如果一切顺利,它们会包含在继承自AQGridView数据源以及AQGridView委托协议的类中。
首先要确定的是网格中所包含的项目数量,现在我们可以先返回一个随机数。以后当我们执行各项服务时,该数字会根据实际情况发生变化。
- - (NSUInteger) numberOfItemsInGridView: (AQGridView *) aGridView
- {
- return 6;
- }
接下来要执行的方法名为cellForItemAtIndex。该方法会在可能时通过CellIdentifier字符串提取一个单元,如果无法提取,它会根据我们之前的执行情况创建一个新的GridViewCell版本。
- - (AQGridViewCell *) gridView: (AQGridView *) aGridView cellForItemAtIndex: (NSUInteger) index
- {
- static NSString * PlainCellIdentifier = @"PlainCellIdentifier";
- GridViewCell * cell = (GridViewCell *)[aGridView dequeueReusableCellWithIdentifier:@"PlainCellIdentifier"];
- if ( cell == nil )
- {
- cell = [[GridViewCell alloc] initWithFrame: CGRectMake(0.0, 0.0, 160, 123)
- reuseIdentifier: PlainCellIdentifier];
- }
- [cell.imageView setImage:[UIImage imageNamed:@"service-2.jpg"]];
- [cell.captionLabel setText:@"Sample service"];
- return cell;
- }
大家可以清楚地看到,每个单元都根据一些虚拟数据获得了配置。
到这里,我们已经执行了很多代码内容,但仍然没有看到任何执行结果。感觉有点心慌,怕出什么问题?别急,咱们马上尝试运行已经完成的部分。
要想在模拟器中获得正确的显示结果,我们需要先向Storyboard声明这套新的ViewController。
选择MainStoryboard_iPhone文件,将SeconVIewController nib文件变更为GridViewController类。另外,别忘了删除视图中的两个选项卡。
现在我们已经万事俱备,可以开始在模拟器运行这款小应用了。运行后的结果应该是如下图所示。
很失望吧?这跟咱们预想的效果根本不一样嘛。别担心,让我们一起看看哪里出了问题。
执行网格布局
第一步是改变背景颜色。为了实现该目标,我们将要使用纤维纹理素材,这在第一部分中已经提到过了。
打开GridViewController.m文件,将以下两行代码添加到viewDidLoad方法当中:
- UIImage * backgroundPattern = [UIImage imageNamed:@"bg-app.png"];
- [self.view setBackgroundColor:[UIColor colorWithPatternImage:backgroundPattern]];
接下来我们需要执行AQGridView数据源协议方法:
- - (CGSize) portraitGridCellSizeForGridView: (AQGridView *) aGridView
- {
- return ( CGSizeMake(160.0, 123) );
- }
该方法的作用是通知网格视图每个单元的具体尺寸是多大。对应尺寸来自我们之前所创建的GridViewCell。
现在再次尝试用模拟器运行应用程序,结果应该如下图所示。
没错,这才对嘛!
执行数据模型
说到这里,我们的单元似乎还略显单调,需要增添一些多样性。尝试将数据模型加入进来可以使服务项目与样本数据相结合,进而令应用程序更具说服力。这才是企业理想中的服务宣传平台,我们的应用当然也得达到同样的水准。除此之外,大家当然还可以在应用中添加内容管理系统等其它要素,进一步丰富应用内容,不过这就不是本系列教程所要讨论的话题啦。
选择Cocoa Touch中的NSObject选项在应用程序中添加一个新文件,并将其命名为BusinessService。打开BuisinessService.h文件,然后添加以下代码:
- #import <Foundation/Foundation.h>
- @interface BusinessService : NSObject
- @property (nonatomic, copy) NSString* caption;
- @property (nonatomic, retain) UIImage* image;
- -(id)initWithCaption:(NSString*)theCaption andImage:(UIImage*)theImage;
- +(NSArray*)getSampleData;
- @end
这个类非常简单,其中只包含标题及一张图像。它同时定义了两套方法,这一点我会在稍后详细解释。
打开BusinessService.m文件,将以下代码段添加进去:
- @synthesize caption, image;
- -(id)initWithCaption:(NSString*)theCaption andImage:(UIImage*)theImage
- {
- self = [super init];
- if(self)
- {
- self.caption = theCaption;
- self.image = theImage;
- }
- return self;
- }
- +(NSArray*)getSampleData
- {
- BusinessService* service1 = [[BusinessService alloc] initWithCaption:@"Litigation" andImage:[UIImage imageNamed:@"service-1.jpg"]];
- BusinessService* service2 = [[BusinessService alloc] initWithCaption:@"Family Law" andImage:[UIImage imageNamed:@"service-2.jpg"]];
- BusinessService* service3 = [[BusinessService alloc] initWithCaption:@"Conveyancing" andImage:[UIImage imageNamed:@"service-3.jpg"]];
- BusinessService* service4 = [[BusinessService alloc] initWithCaption:@"Corporate Law" andImage:[UIImage imageNamed:@"service-4.jpg"]];
- BusinessService* service5 = [[BusinessService alloc] initWithCaption:@"Solicitors" andImage:[UIImage imageNamed:@"service-5.jpg"]];
- BusinessService* service6 = [[BusinessService alloc] initWithCaption:@"Tax Law" andImage:[UIImage imageNamed:@"service-6.jpg"]];
- return [NSArray arrayWithObjects:service1, service2, service3, service4, service5, service6, nil];
- }
上述代码的作用是执行一套init方法,其中标题与图像都通过函数中的参数进行了初始化。GetSampleData方法以不同的标题与图像调用了六次init函数。
现在我们要做的是将模型与网格视图关联起来。打开GridViewController.m文件,并将以下代码添加到ViewDidLoad方法当中(别忘了在#import部分补上‘BusinessService.h’文件)。
- self.services = [BusinessService getSampleData];
这样样本数据就会被载入到服务项目当中。
现在我们需要修改numberOfItemsInGridView内容,以确保返回值与服务项目数量相吻合:
- - (NSUInteger) numberOfItemsInGridView: (AQGridView *) aGridView
- {
- return [services count];
- }
最后,修改cellForItemAtIndex方法,以使用特定索引中的服务项目。也就是说每个单元都要使用与之相对应的服务信息(包括标题及图像)。
- - (AQGridViewCell *) gridView: (AQGridView *) aGridView cellForItemAtIndex: (NSUInteger) index
- {
- static NSString * PlainCellIdentifier = @"PlainCellIdentifier";
- GridViewCell * cell = (GridViewCell *)[aGridView dequeueReusableCellWithIdentifier:@"PlainCellIdentifier"];
- if ( cell == nil )
- {
- cell = [[GridViewCell alloc] initWithFrame: CGRectMake(0.0, 0.0, 160, 123)
- reuseIdentifier: PlainCellIdentifier];
- }
- BusinessService* service = [services objectAtIndex:index];
- [cell.imageView setImage:service.image];
- [cell.captionLabel setText:service.caption];
- return cell;
- }
现在再次运行应用程序,看看结果如何。
哈哈,颇具时代感,不是吗:-) 现在我们只剩最后一项工作,那就是在屏幕顶部添加蓝色的导航栏。
自定义导航栏
要显示导航栏,我们必须先将其嵌入到导航控制器当中。打开MainStoryboard_iPhone文件并选择GridViewController。接着打开Editor下拉菜单、点选Embed In中的Navigation Controller项。
如果现在就运行应用,那么我们会看到默认状态下的导航栏。这不够好,还需要进一步调整完善。这里我们要用到iOS 5 Appearance SDK,这是一款专门处理外观任务的工具,能够设置应用程序中出现的所有UI元素。
打开AppDelegate.m文件,并将didFinishLaunchingWithOptions变更为如下内容:
- - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- {
- UIImage *navBarImage = [UIImage imageNamed:@"menubar.png"];
- [[UINavigationBar appearance] setBackgroundImage:navBarImage
- forBarMetrics:UIBarMetricsDefault];
- // Override point for customization after application launch.
- return YES;
- }
这样做是为了将应用程序中所有UI导航栏的背景图案变更为特定内容(menubar.png)。
为导航栏添加“Services”标题,我们可以在Storyboard中双击文本内容来进行编辑。
最后一步是为网格顶部添加渐变效果,这样导航栏看起来将更富动感。
为了实现这一目标,我们需要将CALayer渐变层添加到GridViewController.m文件当中。
包括QuartzCore头文件:
- #import <QuartzCore/QuartzCore.h>
然后将以下代码添加到ViewDidLoad方法末尾:
- UIView* gradientView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 4)];
- CAGradientLayer *gradient = [CAGradientLayer layer];
- gradient.frame = gradientView.bounds;
- UIColor* lightColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
- UIColor* darkColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
- gradient.colors = [NSArray arrayWithObjects:(id)darkColor.CGColor, (id)lightColor.CGColor, nil];
- [gradientView.layer insertSublayer:gradient atIndex:0];
- [self.view addSubview:gradientView];
现在我们最后运行一次,看看应用程序的执行效果。
总结
到这里,系列指南文章的第二部分就结束了。在接下来的第三部分中,我将向大家展示如何为每项服务设计视图细节。当用户轻触服务标签时,应用会直接在屏幕上切换出新的ViewController,而我们的后续设计工作也将就此展开。希望到时候大家还能来继续捧场!
如果朋友们有疑问或者建议,不妨在评论栏中与大家分享并讨论。
原文链接:
http://mobile.tutsplus.com/tutorials/iphone/design-build-a-small-business-app-aqgridview/