() translation by (you can also view the original English article)
Привлекайте своих пользователей потрясающими каруселями. Мы посмотрим, насколько легко и просто внедрить прокручиваемые интерактивные карусели в приложения для iOS. Высокая конфигурируемость позволяет создавать трехмерные, плоские, вращающиеся и бесконечные массивы прокрутки для данных, изображений или кнопок.
Некоторые аспекты приложений или методов, использованных в этом руководстве, изменились с момента его первоначального опубликования. Это может сделать его немного сложным. Мы рекомендуем взглянуть на более поздние учебники по той же теме:
9 января 2007 года Стив Джобс представил iPhone заинтересованной аудитории. В своем выступлении он продемонстрировал многие функции, которые позволят создать совершенно новый способ взаимодействия с технологиями и информацией. Одна из многочисленных функций была представлена простым и мощным сообщением - "прикоснись к своей музыке". Когда он стоял там, с Бобом Диланом, играющим над динамиками, Стив Джобс "пролистал" музыкальные альбомы без особых усилий, и это сообщение было ясным.
Теперь, почти пять лет спустя, это же сообщение верно. В том, как мы можем просматривать нашу музыку сегодня, есть волшебство, и, как разработчики, мы можем донести этот же опыт до наших пользователей для всех видов данных, а не только для песен и альбомов.
Для тех, кто уже знаком с разработкой для iOS, может быть пугающим рассмотреть ряд факторов, влияющих на реализацию чего-то, казалось бы простого, например Cover Flow: анимация и плавная прокрутка, оптимизация обработки изображений, перехват сенсорных взаимодействий и т. д.
К счастью, Ник Локвуд из Charcoal Design создал класс под названием "iCarousel", который выполняет всю тяжелую работу для нас, и он выпустил его как проект с открытым исходным кодом. Это означает, что мы можем быстро и эффективно приступить к работе, все еще наслаждаясь высоко интерактивным, сенсорным Cover Flow.
Одной из замечательных особенностей iCarousel является выбор готовых к использованию типов дисплеев:
- iCarouselTypeLinear
- iCarouselTypeRotary
- iCarouselTypeInvertedRotary
- iCarouselTypeCylinder
- iCarouselTypeInvertedCylinder
- iCarouselTypeCoverFlow
- iCarouselTypeCoverflow2
Также возможно настроить эти стили в соответствии с вашими потребностями, но это может быть отдельный учебник или краткий совет (сообщите нам в комментариях, если вы заинтересованы).
Шаг 1: Получение iCarousel и настройка
iCarousel размещен на github, что означает, что вы можете получить его либо в виде git-клона, либо в виде файла .zip. Вы можете найти его по адресу https://github.com/nicklockwood/iCarousel, так что получите локальную копию iCarousel.
В этом проекте также используется несколько изображений, поэтому вы можете скачать "Исходные файлы" (Source Files) вверху этой страницы, если вы этого еще не сделали. В этом файле .zip есть каталог под названием "Animals” (Животные), который имеет семь разных изображений. (Эти изображения получены от Joy Tek на Flickr (http://www.flickr.com/photos/joytek/collections/72157627168953450/) и были изменены в этом учебнике.)
Теперь, когда все необходимые файлы загружены, мы готовы создать потрясающую карусель!
Мы начнем с добавления файлов классов iCarousel, затем файлов изображений и, наконец, мы ограничим приложение в альбомном режиме без видимой строки состояния. (iCarousel будет работать в портретном режиме, но мы пока упростим его, пока работаем с альбомной ориентацией.) Но прежде всего давайте создадим новый проект.
Нам нужно одно окно для этого проекта, так что «Single View Application" (Шаблона с одним готовым окном) будет достаточно. Я назову свой проект "Карусель" (Carousel), и буду использовать автоматический подсчет ссылок, поэтому важно не забыть включить эту опцию.






После того, как наш проект создан, мы можем добавить файлы класса iCarousel, захватив каталог "iCarousel" и перетащив его в проект. (В каталоге iCarousel есть только два файла: "iCarousel.h" и "iCarousel.m"). Примечание. Если вы перетаскиваете весь каталог в свой проект, убедитесь, что вы создали группы для любых добавленных папок.



iCarousel зависит от инфраструктуры QuartzCore и в настоящее время не поддерживает ARC, поэтому у нас есть несколько простых задач, чтобы убедиться, что наш новый добавленный класс будет работать с нашим проектом.
Чтобы добавить платформу QuartzCore, щелкните файл проекта в левом навигаторе (это будет ваше имя проекта; у меня "iCarousel 1target, iPhone OS..."). Теперь в верхней части экрана у вас есть некоторые настройки сборки. Нажмите "Build Phases" (Этапы сборки), а затем разверните "Link Binary With Libraries" (Связать двоичные файлы с библиотеками) и нажмите кнопку "+" в нижнем левом углу. Появится окно, и вы можете найти нашу платформу, набрав "QuartzCore" в поле поиска. Нажмите "Add" (Добавить), и все готово.






Затем мы установим флаг компиляции, который сделает исключение для компилятора LLVM для iCarousel. Перейдите в раздел "Compile Sources" (Компилировать исходники) на той же странице, и мы перейдем к записи "iCarousel". Дважды щелкните по этой строке и поместите "-fno-objc-arc" (без кавычек) в появившемся всплывающем окне.



Мы собираемся отключить строку состояния для этого приложения, поэтому перейдите на вкладку "Info" (Информация) для нашей задачи и в разделе "Custom iOS Target Properties" (Пользовательские свойства цели iOS" добавим новую строку (Щелкните правой кнопкой мыши ->; Добавить ряд (Add Row)) и установите для текста в поле "Key" (Ключ) значение "Status bar is initially hidden" (Строка состояния изначально скрыта). Затем установите "Value" на "YES".
Теперь, перед тем как приступить к реализации, мы хотим установить ориентацию нашего приложения в альбомную и убедиться, что оно не переходит в портретный режим (по крайней мере, на данный момент). Мы просто перейдем на вкладку "Summary" (Сводка) и убедитесь, что параметры "Landscape Left” (Левый горизонтальный) и "Landscape Right” (Правый горизонтальный) являются единственными, выбранными в разделе "Supported Device Orientations” (Поддерживаемые ориентации устройств).



Затем мы можем зайти в наш файл реализации контроллера основного вида ("MTViewController.m" для меня) и изменить метод:
1 |
|
2 |
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation |
3 |
{
|
4 |
// Return YES for supported orientations
|
5 |
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight); |
6 |
}
|
Последнее, что нам нужно сделать - это вставить изображения нашего зоопарка в наш проект. Я включил семь таких изображений в исходные файлы, которые вы можете использовать. Просто возьмите их и перетащите их в наш проект. (Вы также можете просто перетащить весь каталог "Animals", в который будут включены все изображения.) И теперь мы готовы к работе!

Шаг 2: Настройка наших данных и карусели
Наша Карусель покажет некоторые изображения различных животных зоопарка, а под текущим изображением мы покажем название животного и то, какую пищу оно любит есть. При разработке продукта у вас должны быть реальные данные для работы, но для нашего примера мы просто настроим несколько NSArrays с фиктивными данными.
Наш первый массив будет список имен изображений, чтобы мы могли найти и загрузить их в нашу карусель. Мы назовем этот список "images”.
Второй массив будет иметь список имен, которые соответствуют нашим изображениям, а также небольшое предложение, следующее за этим форматом: [animal name] Eat: [food]. Например, с медведями мы скажем: "Медведи едят: мед". Мы будем называть этот массив "descriptions”.
Мы настроим эти NSArrays в нашем заголовочном файле контроллера основного вида ("MTViewController.h" для меня).
1 |
|
2 |
@property (strong, nonatomic) NSMutableArray *animals; |
3 |
@property (strong, nonatomic) NSMutableArray *descriptions; |
И, конечно же, синтезировать их в нашем файле реализации:
1 |
|
2 |
@synthesize animals, descriptions; |
Поскольку в этом примере мы используем .xib, нам нужно выполнить настройку в методе "initWithNibName". Давайте теперь поместим имена изображений и описания продуктов в их массивы.
1 |
|
2 |
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil |
3 |
{
|
4 |
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; |
5 |
if (self) { |
6 |
|
7 |
//set up carousel data
|
8 |
wrap = NO; |
9 |
|
10 |
self.animals = [NSMutableArray arrayWithObjects:@"Bear.png", |
11 |
@"Zebra.png", |
12 |
@"Tiger.png", |
13 |
@"Goat.png", |
14 |
@"Birds.png", |
15 |
@"Giraffe.png", |
16 |
@"Chimp.png", |
17 |
nil]; |
18 |
|
19 |
self.descriptions = [NSMutableArray arrayWithObjects:@"Bears Eat: Honey", |
20 |
@"Zebras Eat: Grass", |
21 |
@"Tigers Eat: Meat", |
22 |
@"Goats Eat: Weeds", |
23 |
@"Birds Eat: Seeds", |
24 |
@"Giraffes Eat: Trees", |
25 |
@"Chimps Eat: Bananas", |
26 |
nil]; |
27 |
}
|
28 |
|
29 |
return self; |
30 |
}
|
Вы заметите, что есть также свойство "wrap", для которого мы установили "NO”. Это свойство iCarousel, и оно гарантирует, что наша карусель не прокручивает бесконечный цикл по нашим изображениям, но вместо этого она прекращает прокручивать после первого и последнего элементов. Мы рассмотрим это позже.
Теперь, когда у нас есть некоторые данные в нашем приложении, нам нужно реализовать фактический класс iCarousel. iCarousel работает как UITables с протоколами "data source” и "delegate”. Мы реализуем это, сначала импортировав класс iCarousel в наш заголовок.
1 |
|
2 |
#import "iCarousel.h”
|
Далее мы добавим следующий фрагмент кода после части "UIViewController" в заголовке интерфейса:
1 |
|
2 |
<CarouselDataSource, iCarouselDelegate>; |
Пока мы здесь, мы также можем добавить свойство "wrap", которое мы установили в нашем методе "initWithNibName".
1 |
|
2 |
@property (nonatomic) BOOL wrap; |
Теперь, когда наш заголовок полностью готов, нам нужно соединить UIView и UILabel, которые нам понадобятся для отображения нашей карусели и текста описания. Итак, мы откроем наш файл .xib (для меня "MTViewController.xib") и добавим наши новые элементы.
Для iCarousel нам понадобится UIView. Я устанавливаю свой фон "Lead”, чтобы за изображениями было хорошо и темно.



Теперь, чтобы iCarousel распознал этот UIView как подкласс "iCarousel", мы перейдем к "identity inspector” и изменим "Class” на "iCarousel" в разделе "Custom Class”. Затем, если мы щелкнем правой кнопкой мыши на нашем новом UIView, мы можем перетащить наши параметры "dataSource" и "delegate” в "File’s Owner”. Нам также нужно будет настроить "Referencing Outlet” для нашего просмотра карусели на свойство "carousel” в нашем "File’s Owner”. Мы почти закончили с iCarousel, но сначала мы поработаем над нашим лейблом, а затем подключим к нашему классу "MTViewController”.




Итак, я собираюсь установить фон для основного вида на "Tungsten”, что обеспечит более светлую серую область для фона, которая будет показывать текст описания выбранного животного. И затем, я перетащу UILabel и расположу по центру под моим iCarousel UIView.
Теперь, когда все готово, я могу открыть "Assistant Editor”, легко щелкнуть правой кнопкой мыши и перетащить мои новые представления: сначала представление iCarousel прямо под массивом "descriptions” в заголовочном файле основного представления, а затем я сделаю то же самое с моей UILabel. Я назвал мой вид карусели "carousel”, а мой UILabel - "label".



И это завершает нашу работу с файлом заголовка, а также с файлом .xib. Таким образом, мы импортировали класс iCarousel, добавили протокол данных iCarousel и протоколы делегатов, а также создали наши свойства для карусели, метки и массивов.
Шаг 3: Заставить все это работать
Протокол iCarousel поддерживает ряд методов, которые работают со всеми визуальными и интерактивными элементами карусели. Вы можете найти полную ссылку на доступные методы, свойства и т. д. На странице iCarousel в github здесь: https://github.com/nicklockwood/iCarousel. На данный момент нам просто нужно настроить наши массивы в качестве данных для нашей карусели, а также настроить поведение карусели.
В этом примере это методы iCarousel, которые мы будем использовать:
1 |
|
2 |
- (NSUInteger)numberOfItemsInCarousel:(iCarousel *)carousel |
3 |
{
|
4 |
return [animals count]; |
5 |
}
|
Мы установим общее количество элементов в нашем массиве "animals”.
1 |
|
2 |
- (NSUInteger)numberOfVisibleItemsInCarousel:(iCarousel *)carousel |
3 |
{
|
4 |
//limit the number of items views loaded concurrently (for performance reasons)
|
5 |
return 7; |
6 |
}
|
Для iPhone мы хотим отображать до 7 элементов одновременно. Это не абсолютное число, но будет полезно для производительности.
1 |
|
2 |
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index |
3 |
{
|
4 |
//create a numbered view
|
5 |
UIView *view = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[animals objectAtIndex:index]]]; |
6 |
return view; |
7 |
}
|
Это очень похоже на работу с текущей ячейкой в UITableView. Здесь мы устанавливаем содержимое каждого элемента карусели как UIView с UIImage. UIImage загрузит .png для соответствующего животного в массиве "animals".
1 |
|
2 |
- (NSUInteger)numberOfPlaceholdersInCarousel:(iCarousel *)carousel |
3 |
{
|
4 |
//note: placeholder views are only displayed on some carousels if wrapping is disabled
|
5 |
return 0; |
6 |
}
|
Заполнители - форзацы в начале и конце нашей группы изображений. Мы не хотим этого, поэтому мы вернем 0. Ради интереса, не стесняйтесь изменить это, чтобы вернуть 1, но для нашего примера мы хотим оставить все как есть.
1 |
|
2 |
- (CGFloat)carouselItemWidth:(iCarousel *)carousel |
3 |
{
|
4 |
//usually this should be slightly wider than the item views
|
5 |
return 240; |
6 |
}
|
Довольно понятно, вот сколько места будет уделять карусель каждому предмету. Наши изображения имеют ширину 220px, поэтому я установил его на 240, чтобы обеспечить некоторый интервал.
1 |
|
2 |
- (BOOL)carouselShouldWrap:(iCarousel *)carousel |
3 |
{
|
4 |
//wrap all carousels
|
5 |
return wrap; |
6 |
}
|
В нашем методе "initiWithNibName" для этого параметра установлено значение "no”, и наши элементы будут прокручиваться бесконечно.
1 |
|
2 |
- (void)carouselDidEndScrollingAnimation:(iCarousel *)aCarousel |
3 |
{
|
4 |
[label setText:[NSString stringWithFormat:@"%@", [descriptions objectAtIndex:aCarousel.currentItemIndex]]]; |
5 |
}
|
И наконец, это метод, который будет запускаться, когда мы остановимся на данном элементе. Мы устанавливаем текст нашего UILable в соответствии с содержимым нашего массива "descriptions" в соответствующем индексе для нашего текущего элемента. И это все для методов iCarousel.
Последнее, что мы хотим сделать сейчас, перед запуском нашего приложения, - это установить тип представления карусели, который нам нужен. Мы можем сделать это в методе "(void)viewDidLoad”, установив carousel.type в наш желаемый стиль.
1 |
|
2 |
- (void)viewDidLoad |
3 |
{
|
4 |
carousel.type = iCarouselTypeCoverFlow2; |
5 |
[super viewDidLoad]; |
6 |
}
|
Вы можете увидеть полный список стилей в начале этой статьи или на странице iCarousel github.
А теперь продолжайте, создавайте и запускайте свое приложение, и вы увидите прокручиваемый список изображений животных с описаниями внизу. Я настоятельно рекомендую вам поиграть с различными стилями и свойствами карусели, и, возможно, в будущем мы даже сможем взглянуть на интерактивность с элементами карусели.