Это третий выпуск из серии о создании iPad-ридера для книги «Война миров» . В сегодняшнем уроке я покажу, как добавить оглавление в проект. При этом я расскажу о работе с plist-файлами, наложением слоев, базовыми анимациями UIView и ручным созданием компонентов интерфейса.
Где мы остановились
В уроке , представленном на прошлой неделе , я продемонстрировал, как добавить в проект UISlider
, который позволил бы пользователю быстро «пролистывать» вперед или назад PDF-файл « Войны миров» . Это важная функция для любого PDF-ридера, но она по-прежнему ложится тяжелым бременем на пользователя, если он хочет перейти к определенной главе или разделу. Следовательно, добавление оглавления (далее именуемого просто «оглавление») выглядело как следующий логический шаг, и в опросе, приложенном к последнему уроку, 68% наших читателей проголосовали за это. В сегодняшних шагах я покажу вам, как это сделать.
Важно отметить, что в тексте « Войны миров», который используется в этом руководстве, еще нет страницы оглавления в документе PDF. Следовательно, мы сосредоточимся на создании собственного TOC UIView
.
Последнее замечание перед тем, как мы начнем: пока это руководство в первую очередь полагалось на Интерфейсный Разработчик для настройки и создания пользовательского интерфейса. В этом уроке я отойду от Interface Builder и создам несколько новых компонентов интерфейса UIKit программным способом в нашем главном контроллере представления. Иногда я предпочитаю управлять созданием пользовательского интерфейса таким образом, поэтому я решил показать его как альтернативный подход в образовательных целях. Просто поймите, что все компоненты UIKit, которые я создаю в коде, могли быть созданы в Интерфейсном Разработчике и распакованы из NIB.
Шаг 1: Создайте кнопку TOC
Лучшие приложения для чтения на iPad предоставляют пользователям постоянную кнопку, которая будет переходить непосредственно к оглавлению книги. Мы сделаем то же самое здесь, добавив UIButton
в верхнем правом углу дисплея книги. Мы могли бы легко сделать эту кнопку иконкой или нарисовать ее простым градиентом, но вместо этого мы сделаем все просто. Кнопка будет иметь прозрачный фон, синий текст и текст «Содержание» в качестве заголовка.
Для начала откройте WOTWViewController.h и добавьте следующий элемент данных:
1
2
3
4
5
|
@interface WOTWViewController : LeavesViewController {
CGPDFDocumentRef bookPDF;
UIButton *contentsButton;
UISlider *pageSlider;
}
|
Пока вы находитесь в файле интерфейса, продолжайте и объявите метод, который будет отвечать за создание кнопки вручную:
} @property (nonatomic, retain) IBOutlet UISlider * pageSlider; - (недействительно) loadPDF; - (void) addContentsUIButton;
Затем переключитесь на файл WOTWViewController.m и addContentsUIButton
метод addContentsUIButton
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
— (void)addContentsUIButton
{
if(!contentsButton)
{
// Basic Initialization
contentsButton = [[UIButton alloc] initWithFrame:CGRectMake(460.0f, 5.0f, 100.0f, 45.0f)];
[contentsButton setTitle:@»Contents» forState:UIControlStateNormal];
[contentsButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[contentsButton setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
contentsButton.backgroundColor = [UIColor clearColor];
// When the button is tapped, trigger the «displayTableOfContents» method
[contentsButton addTarget:self action:@selector(displayTableOfContents) forControlEvents:UIControlEventTouchUpInside];
// Hide the button by default as it shouldn’t show on the book cover
contentsButton.hidden = YES;
// Add the button as a subview of LeavesView
[self->leavesView addSubview:contentsButton];
}
}
|
Поскольку одновременно должна существовать только одна кнопка содержимого, мы начинаем этот метод со строки 3, проверяя, что мы еще не создали и не добавили эту кнопку в представление «Листья». Если у нас есть, вызов метода просто не будет выполнять любой код создания кнопки.
Строки 5 — 10 — это несколько стандартных операторов создания кнопок. Стоит отметить, что в строке 6 вызывается метод -initWithFrame:
который является назначенным инициализатором для UIButton
, и настраивается для кнопки значение 460 по оси x, значение 5 по оси y, ширина 100 и высота 45. Стоит также отметить, что свойства title
и titleColor
UIButton
зависят от состояния. Это позволяет визуально реагировать на такие события, как нажатие или отключение кнопки.
Если раньше вы только создавали кнопки с помощью Interface Builder, в строке 12 все становится немного интереснее. В этой строке показано, как вручную установить, какой селектор должен вызываться для одного из различных событий управления кнопками. Если вам интересно, как Interface Builder достиг этого, то теперь это должно быть немного яснее.
Далее скрытое свойство кнопки устанавливается на «ДА». Это происходит потому, что читатель изначально загружается с отображенной обложкой книги, и кажется неуместным показывать ссылку на оглавление, по крайней мере, до следующей страницы.
В строке 19 мы добавляем наш вновь созданный UIButton
непосредственно в объект LeavesView
в качестве подпредставления. Кажется логически логичным сделать эту кнопку частью LeavesView, и это не позволит нам вспомнить переключение как LeavesView, так и кнопки содержимого при отображении оглавления. Также можно интегрировать кнопку содержимого с анимацией оглавления, используя этот подход (подробнее об этом позже).
Конечно, мы еще не совсем закончили. Нам все еще нужно вызывать этот метод где-то в жизненном цикле программы, и нам также нужно отпустить выделенную нами кнопку.
-viewDidLoad
методу -viewDidLoad
, чтобы добавить кнопку с этой строкой кода:
— (void) viewDidLoad
1
|
[self addContentsUIButton];
|
Это кажется хорошим местом для добавления кнопки TOC, но вы задаетесь вопросом, почему я пытаюсь использовать вызов метода вместо простого написания кода в этом методе изначально? Когда я впервые создавал эту функцию, я сделал. Однако при первоначальном добавлении всего кода непосредственно в viewDidLoad
все стало действительно грязно, и было сложнее получить общее представление о том, что происходило в течение жизненного цикла приложения. Разделение больших кусков кода на независимые методы решило эту проблему и сделало проект более понятным и поддерживаемым.
Поскольку мы выделили кнопку содержимого из viewDidLoad
, мы должны также отпустить ее как в -viewDidUnload
и в -dealloc
.
— (void) viewDidUnload
1
|
[contentsButton release], contentsButton = nil;
|
— (недействительно) dealloc
1
|
[contentsButton release];
|
Вспомните сверху, что мы изначально установили contentsButton
скрытым. Нам нужно добавить несколько строк кода в LeavesView
делегата -leavesView:didTurnToPageAtIndex:
чтобы показать кнопку содержимого после того, как пользователя больше нет на титульной странице. Это достаточно просто:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
— (void) leavesView:(LeavesView *)leavesView didTurnToPageAtIndex:(NSUInteger)pageIndex
{
if((int) self.pageSlider.value != pageIndex)
{
self.pageSlider.value = (float) pageIndex;
}
if(pageIndex > 0)
{
contentsButton.hidden = NO;
}
else
{
contentsButton.hidden = YES;
}
}
|
Если вы строите и запускаете проект на этом этапе, вы должны увидеть кнопку содержимого, наложенную в верхнем правом углу представления книги. Однако, если вы на самом деле нажмете кнопку, приложение displayTableOfContents
потому что мы еще не реализовали селектор displayTableOfContents
, который будет пытаться вызвать действие кнопки.
Шаг 2. Создание оглавления UIView
С кнопкой содержимого на месте, пришло время сосредоточиться на построении представления содержания. Мы возьмем тот же подход, который использовался выше, поэтому вернитесь к файлу WOTWViewController.h и добавьте следующий элемент данных:
1
|
UIView *tableOfContentsView;
|
Затем объявите метод для обработки добавления оглавления в LeavesView:
1
|
— (void) addTableOfContentsUIView;
|
Теперь перейдите к WOTWViewController.m и добавьте код, необходимый для создания TOC UIView
:
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
36
37
38
39
40
41
42
|
— (void) addTableOfContentsUIView
{
if(!tableOfContentsView)
{
// Create the TOC UIView.
tableOfContentsView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0, 563.0f, 845.0f)];
tableOfContentsView.backgroundColor = [UIColor whiteColor];
// Create the Book Title.
UILabel *bookHeading = [[UILabel alloc] initWithFrame:CGRectMake(170.0f, 30.0f, 300.0f, 40.0f)];
bookHeading.font = [UIFont fontWithName:@»Arial» size:24.0f];
bookHeading.text = @»WAR OF THE WORLDS»;
bookHeading.textColor = [UIColor blackColor];
bookHeading.backgroundColor = [UIColor whiteColor];
[bookHeading sizeToFit];
[tableOfContentsView addSubview:bookHeading];
[bookHeading release];
// Add «BOOK I» subheader as left column header
UILabel *bookOneSubtitle = [[UILabel alloc] initWithFrame:CGRectMake(105.0f, 70.0f, 150.0f, 40.0f)];
bookOneSubtitle.font = [UIFont fontWithName:@»Arial» size:22.0f];
bookOneSubtitle.text = @»BOOK I»;
bookOneSubtitle.textColor = [UIColor blackColor];
bookOneSubtitle.backgroundColor = [UIColor whiteColor];
[bookOneSubtitle sizeToFit];
[tableOfContentsView addSubview:bookOneSubtitle];
[bookOneSubtitle release];
// Add «BOOK II» subheader as right column header
UILabel *bookTwoSubtitle = [[UILabel alloc] initWithFrame:CGRectMake(375.0f, 70.0f, 150.0f, 40.0f)];
bookTwoSubtitle.font = [UIFont fontWithName:@»Arial» size:22.0f];
bookTwoSubtitle.text = @»BOOK II»;
bookTwoSubtitle.textColor = [UIColor blackColor];
bookTwoSubtitle.backgroundColor = [UIColor whiteColor];
[bookTwoSubtitle sizeToFit];
[tableOfContentsView addSubview:bookTwoSubtitle];
[bookTwoSubtitle release];
// Add the TOC directly to the Leaves view, but hide it at «layer» 0
[self->leavesView insertSubview:tableOfContentsView atIndex:0];
}
}
|
Приведенный выше метод создает базовый шаблон для представления TOC. Размеры представления такие же, как у отображения книги / PDF, и я добавил три метки: заголовок книги, подзаголовок для «Книги 1» и подзаголовок для «Книги 2». Это может показаться немного странным: разве « Война миров» не является одной книгой? Сегодня он опубликован в виде одного тома, но первоначально был напечатан в виде серии журналов и принял формат «Книга 1» и «Книга 2». Потому что это формат, который использует PDF, это то, что я встроил и в оглавление.
Если вы понимаете, как мы обрабатывали создание кнопки содержимого на предыдущем шаге, то большая часть приведенного выше кода также будет иметь смысл для вас. Единственное дополнительное примечание, которое стоит сделать, это то, что я снова вставил оглавление в иерархию LeavesView, только на этот раз я «похоронил» представление оглавления, используя insertSubview:atIndex:
чтобы поместить его под всеми другими leavesView
в leavesView
. Скрывая вид с индексом 0, будет легко выявить оглавление, когда пользователь нажмет кнопку, и это также позволит нам легко создать анимацию с переворотом.
Шаг 3: Анимируйте переход TOC
Прежде чем мы продолжим добавлять файлы plist для хранения информации оглавления, давайте продолжим и создадим переход, который будет срабатывать при нажатии кнопки содержимого. Это облегчит тестирование нашей работы.
В WOTWViewController.m добавьте следующие строки кода:
01
02
03
04
05
06
07
08
09
10
11
12
|
— (void)displayTableOfContents
{
// Hide the page slider
self.pageSlider.hidden = YES;
// Animate the transition with a horizontal flip from right to left
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5f];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self->leavesView cache:YES];
[self->leavesView bringSubviewToFront:tableOfContentsView];
[UIView commitAnimations];
}
|
В строке 4 мы устанавливаем скрытый pageSlider
. Это предотвращает попытку пользователя перейти к другому месту в PDF, пока оглавление покрывает отображение книги.
Строки 6 — 11 обрабатывают анимацию переворачивания страницы. Строка 8 устанавливает длительность этой анимации UIViewAnimationTransitionFlipFromRight
половине секунды, а строка 9 указывает тип анимации ( UIViewAnimationTransitionFlipFromRight
), а также представление, к которому должен применяться переход.
Конечно, ни один из приведенных выше кодов не принесет нам пользы, если он не выполняется. Добавьте еще одну строку в -viewDidLoad
чтобы создать представление оглавления:
1
|
[self addTableOfContentsUIView];
|
Если вы создаете и запускаете проект сейчас, у вас должна быть кнопка с работающим содержимым, которая отображает простое представление TOC.
Шаг 4. Храните данные оглавления в файлах Plist
Следующим шагом является добавление заголовков глав в представление TOC. Однако, поскольку мы собираемся динамически создавать главу, нам нужно сначала где-то хранить информацию о главе и странице. Одним из вариантов будет использование NSDictionary и статическое создание информации о главе / странице в WOTWViewController
реализации WOTWViewController
. Это, безусловно, сработает, но при работе с этим типом информации мне часто легче работать с файлами списка свойств (plist). Мы создадим два plist-файла для этого проекта: один для хранения информации для левого столбца («Книга 1»), а второй для хранения информации для второго столбца («Книга 2»).
CTRL + щелчок (или щелчок правой кнопкой мыши) в группе «Файлы поддержки» в Навигаторе проекта XCode. Выберите «Добавить файлы в WOTW». В появившемся окне выберите категорию «Ресурсы», а затем выберите «Список свойств». Нажмите «Далее», а затем введите имя «BookOne» для файла.
Откройте недавно добавленный файл BookOne.plist и добавьте пары ключ / значение, показанные ниже:
Используйте тот же метод для создания BookTwo.plist и измените пары ключ / значение, как показано:
Шаг 5: Добавьте список глав TOC
Теперь, когда мы сохранили информацию о главе / странице для PDF, мы готовы программно создать список глав. Конечно, в дополнение к простому перечислению контента, мы также должны позволить пользователям нажимать на любую из глав, чтобы перейти к этой части PDF. По этой причине каждая глава фактически будет UIButton
.
Подходящее место для добавления списка глав — когда мы впервые создаем представление TOC, поэтому перейдите к - (void) addTableOfContentsUIView
и добавьте следующие строки кода:
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
— (void) addTableOfContentsUIView
{
if(!tableOfContentsView)
{
// Create the TOC UIView.
tableOfContentsView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0, 563.0f, 845.0f)];
tableOfContentsView.backgroundColor = [UIColor whiteColor];
// Create the Book Title.
UILabel *bookHeading = [[UILabel alloc] initWithFrame:CGRectMake(170.0f, 30.0f, 300.0f, 40.0f)];
bookHeading.font = [UIFont fontWithName:@»Arial» size:24.0f];
bookHeading.text = @»WAR OF THE WORLDS»;
bookHeading.textColor = [UIColor blackColor];
bookHeading.backgroundColor = [UIColor whiteColor];
[bookHeading sizeToFit];
[tableOfContentsView addSubview:bookHeading];
[bookHeading release];
// Add «BOOK I» subheader as left column header
UILabel *bookOneSubtitle = [[UILabel alloc] initWithFrame:CGRectMake(105.0f, 70.0f, 150.0f, 40.0f)];
bookOneSubtitle.font = [UIFont fontWithName:@»Arial» size:22.0f];
bookOneSubtitle.text = @»BOOK I»;
bookOneSubtitle.textColor = [UIColor blackColor];
bookOneSubtitle.backgroundColor = [UIColor whiteColor];
[bookOneSubtitle sizeToFit];
[tableOfContentsView addSubview:bookOneSubtitle];
[bookOneSubtitle release];
// Add «BOOK II» subheader as right column header
UILabel *bookTwoSubtitle = [[UILabel alloc] initWithFrame:CGRectMake(375.0f, 70.0f, 150.0f, 40.0f)];
bookTwoSubtitle.font = [UIFont fontWithName:@»Arial» size:22.0f];
bookTwoSubtitle.text = @»BOOK II»;
bookTwoSubtitle.textColor = [UIColor blackColor];
bookTwoSubtitle.backgroundColor = [UIColor whiteColor];
[bookTwoSubtitle sizeToFit];
[tableOfContentsView addSubview:bookTwoSubtitle];
[bookTwoSubtitle release];
// Create NSDictionary objects from column plist files
NSString *bookOneFilepath = [[NSBundle mainBundle]
pathForResource:@»BookOne» ofType:@»plist»];
NSDictionary *bookOneTOC = [[NSDictionary alloc] initWithContentsOfFile:bookOneFilepath];
NSString *bookTwoFilepath = [[NSBundle mainBundle]
pathForResource:@»BookTwo» ofType:@»plist»];
NSDictionary *bookTwoTOC = [[NSDictionary alloc] initWithContentsOfFile:bookTwoFilepath];
// Iterate over reach NSDictionary object and add UIButtons
float colXOffset = 20.0f;
float colYOffset = 100.0f;
NSArray *sortedKeys1 = [[bookOneTOC allKeys] sortedArrayUsingComparator:^(id obj1, id obj2) {
if ([obj1 integerValue] < [obj2 integerValue] ) {
return (NSComparisonResult)NSOrderedAscending;
}
if ([obj1 integerValue] > [obj2 integerValue] ) {
return (NSComparisonResult)NSOrderedDescending;
}
return (NSComparisonResult)NSOrderedSame;
}];
for(NSString *key in sortedKeys1)
{
int pageIndex = [key intValue];
NSString *sectionTitle = [bookOneTOC objectForKey:key];
UIButton *sectionButton = [[UIButton alloc] initWithFrame:CGRectMake(colXOffset, colYOffset, 250.0f, 35.0f)];
[sectionButton setTitle:sectionTitle forState:UIControlStateNormal];
sectionButton.tag = pageIndex;
[sectionButton addTarget:self action:@selector(contentsButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
sectionButton.enabled = NO;
[sectionButton setBackgroundColor:[UIColor lightGrayColor]];
[sectionButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[tableOfContentsView addSubview:sectionButton];
[sectionButton release];
colYOffset += 40.0f;
}
[bookOneTOC release];
colXOffset = 293.0f;
colYOffset = 100.0f;
NSArray *sortedKeys2 = [[bookTwoTOC allKeys] sortedArrayUsingComparator:^(id obj1, id obj2) {
if ([obj1 integerValue] < [obj2 integerValue] ) {
return (NSComparisonResult)NSOrderedAscending;
}
if ([obj1 integerValue] > [obj2 integerValue] ) {
return (NSComparisonResult)NSOrderedDescending;
}
return (NSComparisonResult)NSOrderedSame;
}];
for(NSString *key in sortedKeys2)
{
int pageIndex = [key intValue];
NSString *sectionTitle = [bookTwoTOC objectForKey:key];
UIButton *sectionButton = [[UIButton alloc] initWithFrame:CGRectMake(colXOffset, colYOffset, 250.0f, 35.0f)];
[sectionButton setTitle:sectionTitle forState:UIControlStateNormal];
[sectionButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
sectionButton.tag = pageIndex;
sectionButton.enabled = NO;
[sectionButton addTarget:self action:@selector(contentsButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[sectionButton setBackgroundColor:[UIColor lightGrayColor]];
[tableOfContentsView addSubview:sectionButton];
[sectionButton release];
colYOffset += 40.0f;
}
[bookTwoTOC release];
// Add the TOC directly to the Leaves view, but hide it at «layer» 0
[self->leavesView insertSubview:tableOfContentsView atIndex:0];
}
}
|
Большая часть этого кода должна быть достаточно понятной для промежуточного разработчика. Однако есть несколько частей, которые заслуживают дальнейшего обсуждения.
Синтаксис, используемый в разделе sortedArrayUsingComparator:
будет выглядеть странно, если вы ранее не программировали «Блоки» Objective-C. Полное обсуждение блоков выходит за рамки данного руководства, но важно знать, что для этого приложения код блока просто отвечает за сортировку массива ключей plist по номеру страницы в порядке возрастания. Это гарантирует, что главы будут отображаться в правильном порядке. Если вы хотите узнать больше о блоках, ознакомьтесь с официальной документацией .
Еще одно важное соображение заключается в том, что я отключаю каждый из объектов UIButton
созданных перед добавлением их в представление TOC. Это leavesView
для того, чтобы не дать leavesView
на leavesView
проходить и запускать кнопки, когда оглавление не отображается. Нам нужно снова включить их в методе -displayTableOfContents
. Давайте продолжим и сделаем это сейчас.
Измените метод -displayTableOfContents
следующим образом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
— (void)displayTableOfContents
{
// Hide the page slider
self.pageSlider.hidden = YES;
// Traverse subviews looking for buttons
for (UIView *subview in tableOfContentsView.subviews)
{
if([subview isKindOfClass:[UIButton class]])
{
UIButton *button = (UIButton *) subview;
button.enabled = YES;
}
}
// Animate the transition with a horizontal flip from right to left
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5f];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self->leavesView cache:YES];
[self->leavesView bringSubviewToFront:tableOfContentsView];
[UIView commitAnimations];
}
|
Строки кода, выделенные выше, будут проходить через tableOfContentsView
в tableOfContentsView
ища те, которые соответствуют классу UIButton
. Когда он находит его, он переключает его с отключенного на включенный.
Шаг 6: Ответ на выбор главы
Если вы внимательно изучили код на шаге 5, вы, вероятно, заметили, что всем UIButton
объектам UIButton
был предоставлен селектор contentsButtonPressed:
для события внутренней обработки. Этот шаг создаст этот метод.
В WOTWViewController.m добавьте следующие строки кода:
- (void) contentsButtonPressed: (UIButton *) отправитель { // Обновляем позицию отображения PDF self-> leavesView.currentPageIndex = sender.tag; // Отображаем UISlider self.pageSlider.hidden = NO; self.pageSlider.value = (float) sender.tag; // Анимация PDF обратно наверх подвидов leavesView [UIView beginAnimations: ноль контекст: ноль]; [UIView setAnimationDuration: 0.5f]; [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromLeft forView: self-> leavesView cache: YES]; [self-> leavesView sendSubviewToBack: tableOfContentsView]; [UIView commitAnimations]; // Отключаем кнопки UIB, добавленные в оглавление, когда они не отображаются для (UIView * subview в tableOfContentsView.subviews) { if ([subview isKindOfClass: [UIButton class]]) { UIButton * button = (UIButton *) подпредставление; button.enabled = NO; } } }
На данном этапе нашей серии ничто в приведенном выше коде не должно быть для вас новым, поэтому я не буду подробно останавливаться на том, что происходит. Общие шаги суммированы в комментариях к коду.
Заворачивать
Если вы выполнили действия, описанные выше, теперь у вас должно быть работающее оглавление для читателя « Войны миров» ! Пользователь начнет видеть кнопку содержимого, когда он перейдет на любую страницу, кроме обложки, а нажатие кнопки содержимого перевернет экран книги вертикально, чтобы открыть экран оглавления. Выбор любой из перечисленных глав позволит сразу перейти к этой главе и перевернуть дисплей обратно в книгу.
Должен ли я продолжить эту серию?
За последние два урока в этой серии я закончил опросом, спрашивающим, должен ли я продолжить серию и, если да, то, что я должен написать о следующем. На этот раз, пожалуйста, «голосовать», оставив комментарий ниже. Если вы хотите, чтобы я продолжал писать о программе для чтения PDF с листьями, дайте мне знать, какие функции или усовершенствования, по вашему мнению, должны стать темой следующего урока. Несколько хороших вариантов: адаптация дисплея для различных ориентаций устройства, добавление закладок или сохранение состояния страницы.
С другой стороны, если вы предпочитаете, чтобы мы полностью охватили другую тему iOS SDK, оставьте комментарий, в котором мне будет сказано, о каком аспекте разработки iOS SDK или связанных проектах с открытым исходным кодом вы хотели бы, чтобы я писал о нем.
Чтобы продолжить серию iPad Reader, по крайней мере 10 читателей должны будут прокомментировать продолжение серии до 23 сентября 2011 года.
ОБНОВЛЕНИЕ 17/17/2011: у нас была отличная обратная связь в разделе комментариев, и похоже, что все, кто писал, заинтересованы по крайней мере еще в одном учебнике. Были получены голоса за следующие функции: поддержка ориентации устройства (7 голосов), поддержка закладок (2 голоса), двухстраничное отображение в альбомной ориентации (2 голоса), сохранение состояния страницы (1 голос), аннотация (1 голос), левая перелистывание страниц вправо (1 голос) и динамические ссылки в формате PDF (1 голос). Ориентация на устройства была явным победителем, поэтому в ближайшие 2 недели я постараюсь сделать еще один пост из этой серии, чтобы показать вам, как это можно сделать!
Спасибо за прочтение!