Добро пожаловать во вторую из трех статей нашей серии о создании приложения для малого бизнеса с нуля. Из этого туториала вы узнаете, как реализовать AQGridView в своем проекте, чтобы добиться потрясающего дизайна. Читай дальше!
Обзор учебника
В этом уроке я расскажу о дизайне экрана, который вы видите на рисунке ниже. На экране, который вы видите ниже, есть сетка вкладок, которые можно использовать для отображения услуг компании. Мы собираемся использовать компонент с открытым исходным кодом под названием AQGridView для реализации Grid, который вы видите ниже.
Представления AQGrid ведут себя аналогично UITableViewController, поэтому, если вы знакомы с использованием табличных представлений, вы находитесь в хорошей компании. Если нет, я покажу вам, как. Не стоит беспокоиться!
Добавление ячейки сетки
Итак, первым шагом является загрузка представления AQGrid из GitHub, а затем добавление папки AQGridView в ваш проект. Нам также нужно добавить библиотеку QuartzCore в наш проект, потому что это требуется представлению AQGrid. Нам больше ничего не нужно сейчас.
Теперь мы можем добавить класс, который будет содержать детали для каждой вкладки. Добавить новый файл в проект. Выберите Какао Touch-> Objective -C Class-> NSObject шаблон. Назовите это GridViewCell.
Измените унаследованный объект на AQGridViewCell в заголовочном файле GridViewCell. Это эквивалент UITableViewCell для компонента вида Grid. Кроме того, добавьте представление изображения и метку в тот же файл заголовка.
01
02
03
04
05
06
07
08
09
10
|
#import <UIKit/UIKit.h>
#import «AQGridView.h»
@interface GridViewCell : AQGridViewCell
@property (nonatomic, retain) UIImageView * imageView;
@property (nonatomic, retain) UILabel * captionLabel;
@end
|
В файле реализации GridViewCell.m мы напишем метод инициализации, который создаст Views, Image Views и Label, которые составят одну вкладку.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
— (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;
}
|
Эта функция похожа на функцию init стандартного UITableViewCell. Разница в этом случае в том, что мы делаем некоторую базовую компоновку для представлений, включенных в ячейку. Есть два ImageViews, один для белой рамки вокруг изображения сервиса и другой для картинки, изображающей сам сервис. Пожалуйста, обратитесь к окончательному изображению, чтобы понять, чего мы пытаемся достичь.
Существует также метка, которая будет использоваться в качестве заголовка вкладки.
После создания представлений они добавляются в UIView (только для организации), а затем этот UIView добавляется в саму ячейку.
Создание Grid Controller
Следующим шагом является создание контроллера View, который будет выступать в качестве делегата и источника данных Grid. Добавьте новый файл и используйте шаблон Какао Touch-> Objective -C Class-> NSObject. Назовите это GridViewController. Измените файл GridViewController.h и сделайте его подклассом AQGidViewController. Также добавьте пару полей, которые будут содержать сам GridView и список служб, которые будут в Grid.
01
02
03
04
05
06
07
08
09
10
|
#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.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
@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];
}
|
Добавляется обязательный синтезатор, после чего Grid инициализируется и настраивается. Мы также гарантируем, что текущий класс GridViewController назначен делегатом и источником данных для GridView. Сетка добавляется к текущему представлению, а данные перезагружаются, чтобы убедиться, что мы начинаем с нуля.
Теперь нам нужно реализовать методы, которые должны быть в классе, который наследуется от протоколов AQGridViewDatasource и AQGridViewDelegate.
Первый — это количество элементов в сетке. Мы просто возвращаем случайное число на данный момент. Позже, когда мы реализуем массив сервисов, это число изменится.
1
2
3
4
|
— (NSUInteger) numberOfItemsInGridView: (AQGridView *) aGridView
{
return 6;
}
|
Следующий реализуемый метод называется cellForItemAtIndex. Этот метод удаляет ячейку из очереди, используя строку CellIdentifier, если она может ее найти. Если этого не произойдет, он создаст новую версию нашего GridViewCell, которую мы ранее реализовали.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
— (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;
}
|
Вы также можете видеть, что каждая ячейка настроена с некоторыми фиктивными данными.
До сих пор мы реализовывали много кода, не видя результата реализации. Давайте сделаем быстрый бег, чтобы увидеть, как все обернется.
Чтобы увидеть это представление в симуляторе, нам нужно сообщить нашей раскадровке об этом новом ViewController.
Выберите файл MainStoryboard_iPhone и измените класс пера SecondViewController на GridViewController. Также удалите обе метки в представлении.
Теперь мы готовы запустить наше маленькое приложение в симуляторе. Мы должны увидеть следующий экран.
Расстроен? Не похоже, что вы ожидали, верно? Хорошо, давайте исправим это.
Реализация макета сетки
Первым шагом является изменение цвета фона. Для этого мы будем использовать текстуру ткани, которая включена в пример проекта.
Откройте файл GridViewController.m и добавьте эти две строки в метод viewDidLoad
:
1
2
3
|
UIImage * backgroundPattern = [UIImage imageNamed:@»bg-app.png»];
[self.view setBackgroundColor:[UIColor colorWithPatternImage:backgroundPattern]];
|
Далее нам нужно реализовать метод протокола AQGridViewDataSource:
1
2
3
4
|
— (CGSize) portraitGridCellSizeForGridView: (AQGridView *) aGridView
{
return ( CGSizeMake(160.0, 123) );
}
|
Этот метод сообщает сетке, насколько большой должна быть каждая ячейка. Размер взят из размера GridViewCell, который мы создали ранее.
Если вы сейчас запустите приложение в симуляторе, вы должны увидеть экран ниже:
Теперь это больше похоже на это!
Реализация модели данных
Наши клетки могли бы сделать с немного большим разнообразием. Давайте добавим к нему модель данных, чтобы службы могли поступать из некоторых примеров данных. В идеале это будет список услуг бизнеса, которому принадлежит приложение. Вы можете подключиться к веб-сайту CMS, а также вывести его категории. Тем не менее, это выходит за рамки этого учебника.
Добавьте в приложение новый файл Cocoa Touch-> NSObject и назовите его BusinessService. Откройте файл BusinessService.h и добавьте следующий код:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
#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 и добавьте следующий фрагмент кода
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
@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 6 раз с разными заголовками и изображениями.
Теперь нам нужно подключить нашу модель к Grid View. Откройте файл GridViewController.m и добавьте его в метод viewDidLoad (не забудьте включить файл «BusinessService.h» в раздел #import).
1
|
self.services = [BusinessService getSampleData];
|
Это загрузит образцы данных в наш массив сервисов.
Также измените numberOfItemsInGridView, чтобы получить фактическое количество сервисов:
1
2
3
4
|
— (NSUInteger) numberOfItemsInGridView: (AQGridView *) aGridView
{
return [services count];
}
|
И наконец, измените метод cellForItemAtIndex, чтобы использовать службу по указанному индексу. Это означает, что 6-я ячейка будет использовать информацию (подпись и изображение) для 6-го сервиса.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
— (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 на сцене. Откройте опцию меню редактора и выберите «Внедрить»> «Контроллер навигации».
Если мы запустим приложение, мы получим базовую панель навигации по умолчанию. Нам все еще нужно настроить его. Для этого мы будем использовать iOS 5 Appearance SDK. Это позволяет вам настроить глобальный внешний вид элементов пользовательского интерфейса в вашем приложении.
Откройте файл AppDelegate.m и измените didFinishLaunchingWithOptions на следующее.
01
02
03
04
05
06
07
08
09
10
|
— (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;
}
|
Для этого нужно изменить фоновое изображение всех UINavigationBar в приложении на указанный UIImage (menubar.png).
Чтобы добавить заголовок «Службы» на панели навигации, дважды щелкните его на раскадровке, чтобы отредактировать его.
Последний шаг — добавить градиент вверху сетки, чтобы панель навигации выглядела так, как будто она зависла.
Для этого мы добавим Gradient CALayer в файл GridViewController.m.
Включите заголовочный файл QuartzCore:
1
|
#import <QuartzCore/QuartzCore.h>
|
И добавьте это в конец метода viewDidLoad:
01
02
03
04
05
06
07
08
09
10
11
|
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];
|
Теперь для финального запуска нашего приложения.
Заворачивать
Мы подошли к концу части 2. Посмотрите на часть 3, где я покажу вам, как разработать детальный вид для каждого сервиса. При нажатии на вкладку службы она выводит новый ViewController на экран, и мы также начинаем процесс его разработки. Обязательно зайдите позже!
Если у вас есть какие-либо вопросы, пожалуйста, дайте мне знать в комментариях.