Добро пожаловать в третью и последнюю часть этого сеанса, где мы создали несколько полезных пользовательских представлений. Мы реализовали настраиваемое представление ввода текста, настраиваемое аккордеонное меню и теперь собираемся создать простое настраиваемое представление оповещений. Читай дальше!
Final Effect Preview
Обзор пользовательских предупреждений
Настраиваемое представление оповещений будет альтернативным, простым и приятным представлением оповещений, которое послужит нашей потребности отображать простые сообщения пользователю. Он будет состоять в основном из следующих частей.
- Метка, на которой появится сообщение.
- Панель инструментов под надписью.
- Хорошо кнопка на правой стороне панели инструментов.
- Кнопка отмены на левой стороне панели инструментов.
Вышеизложенное будет находиться вместе в UIView , и представление будет содержаться в основном представлении контроллера представления, который мы создадим для целей этого настраиваемого представления оповещения.
Основное представление контроллера представления будет полупрозрачным, что позволит пользователям не нажимать на что-либо еще в фоновом режиме, пока отображается предупреждение.
Кроме того, окно предупреждения будет выдвигаться с верхней стороны экрана, когда оно должно появиться, и оно будет выдвигаться с обратным движением, когда оно собирается выйти за пределы экрана. Он будет содержать две кнопки, кнопку « ОК» и кнопку « Отмена» . Они могут быть видны или нет в зависимости от потребностей сообщения, которое должно появиться.
Вот образец окончательного результата.
[Конечный продукт демонстрационный фильм здесь]
1. Контроллер пользовательских предупреждений
Шаг 1
Давайте начнем нашу работу с создания новой группы в Xcode для настраиваемого представления предупреждений. Таким образом, мы можем сохранить наши пользовательские представления в чистоте и порядке.
На панели Project Navigator в левой части XCode, нажмите Control + Click (щелкните правой кнопкой мыши) в группе CustomViewsDemo и выберите опцию New Group из всплывающего меню.
Установите пользовательский вид оповещения в качестве имени новой группы.
Шаг 2
Давайте продолжим, создав новый контроллер представления. Ctrl + клик (щелчок правой кнопкой мыши) в группе Custom Alert View и выберите опцию New File … во всплывающем меню.
В новом окне выберите класс Objective C в качестве шаблона для нового файла и нажмите « Далее» .
На следующем шаге выполните следующие задачи.
- Установите имя CustomAlertViewController в качестве содержимого поля Class .
- В Подклассе поля выберите значение UIViewController .
- Убедитесь, что установлен флажок «С XIB для пользовательского интерфейса» .
После выполнения всех этих шагов, нажмите на следующую кнопку.
Это последний шаг перед созданием нашего нового контроллера представления. Единственное, что нам нужно сделать, это убедиться, что Custom Alert View является выбранной группой. Затем нажмите на кнопку «Создать».
2. Настройка интерфейса
Шаг 1
Теперь, когда новый контроллер представления готов, давайте начнем работать с интерфейсом. Нажмите на файл CustomAlertViewController.xib
чтобы Interface Builder отображался на экране. Выключите функцию Autolayout на случай, если кто-то захочет создать представление предупреждений для версий iOS до 6. Вот как вы это сделаете.
- Нажмите на кнопку Utilities на панели инструментов Xcode, чтобы показать панель Utilites, если она не видна.
- Нажмите на Инспектора Файлов .
- Немного прокрутите вниз и нажмите на опцию «Use Autolayout», чтобы отключить его.
Нам также необходимо убедиться, что представление предупреждений работает на 3,5-дюймовых экранных устройствах, поэтому перейдите в Инспектор атрибутов и в разделе « Симулированные метрики » установите для параметра « Размер» значение « Нет» .
Шаг 2
Пришло время добавить некоторые виды интерфейса. Возьмите следующее из библиотеки объектов и установите некоторые свойства, как описано здесь:
- UIView
- Рамка : X: 0,0, Y: 0,0, ширина: 320,0, высота: 180,0
- Цвет фона : R: 204, G: 204, B: 204
- Авторазмер : Гибкая ширина, Гибкая верхняя граница
- UILabel
- Шрифт : Пользовательский
- Семья : Классная доска SE
- Стиль : Обычный
- Размер : 17
- Выравнивание : Центр
- Строки : 4
- Разрывы строк : перенос слов
- Тень : белый цвет
- Смещение тени : по горизонтали: 1, по вертикали: 1
- Рамка : X: 20,0, Y: 7,0, ширина: 280,0, высота: 123,0
- Авторазмер : Гибкая ширина, Гибкая верхняя граница
- UIToolbar
- Оттенок : R: 204, G: 204, B: 204
- Рамка:: X: 0.0, Y: 136.0, ширина: 320.0, высота: 44.0
- UIBarButtonItem
- Положение : левая сторона панели инструментов
- Оттенок : черный цвет
- Идентификатор : Пользовательский
- Название : Отмена
- UIBarButtonItem
- Идентификатор : Гибкое пространство
- UIBarButtonItem
- Положение : правая сторона панели инструментов
- Оттенок : черный цвет
- Идентификатор : Пользовательский
- Название : Хорошо
Вот как должен выглядеть ваш интерфейс.
3. Свойства IBOutlet и методы IBAction
Шаг 1
Теперь, когда интерфейс готов, нам нужно создать некоторые свойства IBOutlet для соединения наших представлений, а также создать пару методов IBAction, чтобы наши кнопки UIBarButtonItem работали. Для этого нам нужен помощник редактора .
Находясь в Интерфейсном Разработчике , нажмите среднюю кнопку раздела Редактора на панели инструментов Xcode, чтобы открыть Ассистент Редактора и выполнить соответствующие подключения.
Шаг 2
Чтобы создать свойства IBOutlet и соединить их с представлениями, убедитесь, что у вас есть видимая структура документа и:
- Ctrl + клик (правый клик) в представлении
- Во всплывающем меню выберите « Новый источник ссылок».
- Перетащите в окно помощника редактора .
Затем просто укажите имя для нового свойства.
На скриншотах выше я продемонстрировал, как создать свойство IBOutlet для UIView, которое содержит все остальные подпредставления. Все свойства IBOutlet, которые необходимо создать в соответствии с описанной выше процедурой, находятся внутри следующего фрагмента кода.
1
2
3
4
5
6
|
@property (weak, nonatomic) IBOutlet UIView *viewMessage;
@property (weak, nonatomic) IBOutlet UILabel *lblMessage;
@property (weak, nonatomic) IBOutlet UIToolbar *toolbar;
@property (strong, nonatomic) IBOutlet UIBarButtonItem *btnOK;
@property (strong, nonatomic) IBOutlet UIBarButtonItem *btnCancel;
@property (weak, nonatomic) IBOutlet UIBarButtonItem *flexSpace;
|
Шаг 3
Давайте создадим необходимые методы IBAction сейчас. Чтобы создать новый метод IBAction для кнопки UIBarButtonItem , мы сделаем следующее:
- Ctrl + клик (правый клик) на кнопке панели.
- Нажмите на опцию « Выбор» в разделе « Отправленные действия » всплывающего меню.
- Перетащите в окно помощника редактора .
Установите имя для нового метода.
В нашем интерфейсе есть две UIBarButtonItems , поэтому вам придется выполнить эту процедуру дважды. Вы сделаете это один раз для кнопки Okay и один раз для кнопки Cancel . Вот оба метода IBAction .
1
2
|
— (IBAction)btnOkayTap:(id)sender;
— (IBAction)btnCancelTap:(id)sender;
|
Они оба будут реализованы позже.
4. Настройка уровня кода
Шаг 1
Было бы неплохо отличить два UIBarButtonItems (кнопки), которые мы ранее добавили, используя их значения тегов. Мы не установили значение тега в Интерфейсном Разработчике , потому что я лично предпочитаю делать это программно. Как вы сами узнаете позже, значения тегов являются ключом к правильной работе кнопок представления предупреждений.
В настоящее время давайте определим две константы, которые будут представлять значения тегов для каждого UIBarButtonItem (кнопка « ОК» и « Отмена» ) представления предупреждений.
Откройте файл CustomAlertViewController.m
и в верхней части сразу после строки #import...
добавьте следующее:
1
2
|
#define OK_BUTTON_TAG 888
#define CANCEL_BUTTON_TAG 999
|
Представление предупреждений будет использовать анимацию, чтобы появляться и исчезать с экрана, поэтому рекомендуется определить константу для продолжительности анимации. Сразу после двух констант, которые мы только что добавили, напишите эту:
1
2
3
|
#define OK_BUTTON_TAG 888
#define CANCEL_BUTTON_TAG 999
#define ANIMATION_DURATION 0.25
|
Шаг 2
Необходимо выполнить несколько инициализаций, но перед этим давайте создадим пользовательский метод init
, предпочтительно сразу после @implementation CustomAlertViewController
.
1
2
3
4
5
6
7
8
|
-(id)init{
self = [super init];
if (self) {
}
return self;
}
|
Здесь нужно сделать четыре вещи:
- Установите цвет фона и альфа-значение представления по умолчанию (self.view).
- Программно рассчитайте высоту метки сообщения, на случай, если высота представления сообщения изменится в Интерфейсном Разработчике.
- Установите значение тега кнопки Okay .
- Установите значение тега для кнопки « Отмена» .
Давайте установим полупрозрачный фон серого цвета для фона по умолчанию.
1
|
[self.view setBackgroundColor:[UIColor colorWithRed:0.33 green:0.33 blue:0.33 alpha:0.75]];
|
Если вы хотите изменить высоту свойства viewMessage
, не беспокойтесь о точной высоте содержащейся UILabel (свойство lblMessage
). Мы рассчитаем это программно.
1
2
3
4
|
[_lblMessage setFrame:CGRectMake(_lblMessage.frame.origin.x,
_lblMessage.frame.origin.y,
_lblMessage.frame.size.width,
_viewMessage.frame.size.height — _toolbar.frame.size.height)];
|
Наконец, давайте установим значения тегов для двух кнопок, которые у нас есть.
1
2
|
[_btnOK setTag:OK_BUTTON_TAG];
[_btnCancel setTag:CANCEL_BUTTON_TAG];
|
Метод init
готов. Наш следующий шаг — объявить и реализовать открытые методы контроллера представления.
5. Реализация публичных методов
Шаг 1
Существует множество открытых методов, которые могут быть реализованы, и многие из них зависят от воображения программиста или уровня функциональных возможностей, ожидаемых от настраиваемого представления предупреждений такого рода. Однако в нашем примере мы собираемся реализовать только методы, касающиеся следующих вопросов:
- Появление представления оповещения в родительском представлении.
- Исчезновение от родительского взгляда.
- Исчезновение от родительского вида мгновенно.
- Переключатель состояния кнопки Okay (удалить / вставить).
- Переключатель состояния кнопки Отмена (удалить / вставить).
- Проверка удаления кнопки Okay .
- Проверка удаления кнопки « Отмена» .
Нажмите на CustomAlertViewController.h
чтобы включить его. Добавьте следующую декларацию в это.
1
2
3
4
5
6
7
|
-(void)showCustomAlertInView:(UIView *)targetView withMessage:(NSString *)message;
-(void)removeCustomAlertFromView;
-(void)removeCustomAlertFromViewInstantly;
-(void)removeOkayButton:(BOOL)shouldRemove;
-(void)removeCancelButton:(BOOL)shouldRemove;
-(BOOL)isOkayButtonRemoved;
-(BOOL)isCancelButtonRemoved;
|
Давайте начнем реализовывать описанные выше методы один за другим, но сначала давайте переключимся на файл CustomAlertViewController.m
.
Шаг 2
showCustomAlertInView:withMessage
, возможно, является наиболее важным методом, поскольку он отвечает за отображение настраиваемого представления предупреждений в целевом представлении, заданном первым параметром. Однако следует отметить несколько важных моментов.
Во-первых, строка состояния; представление предупреждений будет скользить внутрь и наружу с верхней части экрана, поэтому пространство, занимаемое строкой состояния, если оно отображается, является подотчетным. Мы можем легко узнать, виден ли он, и получить его размер. Но есть небольшая ловушка, если строка состояния видна, и нам приходится иметь дело как с книжной, так и с альбомной ориентацией. Почему? Поскольку в портретном режиме размер строки состояния находится в форме Ширина х Высота (например, 320,0 х 20,0), а в альбомном режиме размер находится в форме Высота х Ширина (например, 20,0 х 480,0) . Самый простой способ определить высоту строки состояния — это проверить минимальное значение между шириной и высотой.
Во-вторых, чтобы правильно представить представление предупреждений, мы должны проверять ориентацию при каждом вызове этого метода и соответственно устанавливать рамку представления. Важно отметить, что когда мы находимся в ландшафтном режиме, ширина экрана — это высота для вида, а высота экрана — это ширина для вида . Кроме того, когда строка состояния видна (и в нашем примере это так), создается отступ (слева от вида в альбомном режиме, вверху в портретном режиме), который необходимо устранить. По этой причине мы просто будем использовать метод CGRectOffset
чтобы переместить рамку представления оповещения для значения смещения, равного высоте строки состояния, либо в направлении верхней части, либо слева от родительского представления.
Как я уже говорил, представление сообщения изначально будет -_viewMessage.frame.size.height
, что означает, что viewMessage
точка viewMessage
свойства viewMessage
будет установлена в -_viewMessage.frame.size.height
. Когда мы используем анимацию, чтобы показать ее на экране, мы просто установим исходную точку Y на значение 0.0
, чтобы получить плавный эффект скольжения. Наконец, строка сообщения, переданная в качестве второго параметра в метод, будет установлена на метку, и мы закончили.
После всего сказанного, вот весь метод:
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
-(void)showCustomAlertInView:(UIView *)targetView withMessage:(NSString *)message{
CGFloat statusBarOffset;
if (![[UIApplication sharedApplication] isStatusBarHidden]) {
// If the status bar is not hidden then we get its height and keep it to the statusBarOffset variable.
// However, there is a small trick here that needs to be done.
// In portrait orientation the status bar size is 320.0 x 20.0 pixels.
// In landscape orientation the status bar size is 20.0 x 480.0 pixels (or 20.0 x 568.0 pixels on iPhone 5).
// We need to check which is the smallest value (width or height).
// At first we get the status bar size.
CGSize statusBarSize = [[UIApplication sharedApplication] statusBarFrame].size;
if (statusBarSize.width < statusBarSize.height) {
// If the width is smaller than the height then this is the value we need.
statusBarOffset = statusBarSize.width;
}
else{
// Otherwise the height is the desired value that we want to keep.
statusBarOffset = statusBarSize.height;
}
}
else{
// Otherwise set it to 0.0.
statusBarOffset = 0.0;
}
// Declare the following variables that will take their values
// depending on the orientation.
CGFloat width, height, offsetX, offsetY;
if ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeLeft ||
[[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationLandscapeRight) {
// If the orientation is landscape then the width
// gets the targetView’s height value and the height gets
// the targetView’s width value.
width = targetView.frame.size.height;
height = targetView.frame.size.width;
offsetX = -statusBarOffset;
offsetY = 0.0;
}
else{
// Otherwise the width is width and the height is height.
width = targetView.frame.size.width;
height = targetView.frame.size.height;
offsetX = 0.0;
offsetY = -statusBarOffset;
}
// Set the view’s frame and add it to the target view.
[self.view setFrame:CGRectMake(targetView.frame.origin.x, targetView.frame.origin.y, width, height)];
[self.view setFrame:CGRectOffset(self.view.frame, offsetX, offsetY)];
[targetView addSubview:self.view];
// Set the initial frame of the message view.
// It should be out of the visible area of the screen.
[_viewMessage setFrame:CGRectMake(0.0, -_viewMessage.frame.size.height, _viewMessage.frame.size.width, _viewMessage.frame.size.height)];
// Animate the display of the message view.
// We change the y point of its origin by setting it to 0 from the -height value point we previously set it.
[UIView beginAnimations:@»» context:nil];
[UIView setAnimationDuration:ANIMATION_DURATION];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[_viewMessage setFrame:CGRectMake(0.0, 0.0, _viewMessage.frame.size.width, _viewMessage.frame.size.height)];
[UIView commitAnimations];
// Set the message that will be displayed.
[_lblMessage setText:message];
}
|
Шаг 3
Следующий метод, который мы должны реализовать, — -(void)removeCustomAlertFromView
, который просто заставляет представление предупреждений исчезать с экрана. Здесь нет ничего особенного, чтобы упомянуть здесь, так как он использует простую анимацию, чтобы изменить исходную точку Y в представлении сообщения и сделать так, чтобы она исчезла с помощью эффекта выдвижения. Обратите внимание только на последнюю команду, которая удаляет представление по умолчанию из суперпредставления с некоторой задержкой и после завершения анимации.
01
02
03
04
05
06
07
08
09
10
11
|
-(void)removeCustomAlertFromView{
// Animate the message view dissapearing.
[UIView beginAnimations:@»» context:nil];
[UIView setAnimationDuration:ANIMATION_DURATION];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[_viewMessage setFrame:CGRectMake(0.0, -_viewMessage.frame.size.height, _viewMessage.frame.size.width, _viewMessage.frame.size.height)];
[UIView commitAnimations];
// Remove the main view from the super view as well after the animation is finished.
[self.view performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:ANIMATION_DURATION];
}
|
Метод -(void)removeCustomAlertFromViewInstantly
является самым простым, поскольку он просто удаляет представление по умолчанию из суперпредставления.
1
2
3
|
-(void)removeCustomAlertFromViewInstantly{
[self.view removeFromSuperview];
}
|
Шаг 4
Далее нам нужно написать методы -(BOOL)isOkayButtonRemoved
и -(BOOL)isCancelButtonRemoved
. Оба они играют важную роль в функциональности представления предупреждений, и по их именам вы можете легко понять, почему. Эти методы могут быть закрытыми, так как я не вызываю их напрямую из демонстрационного приложения. Однако в реальном приложении они могут быть полезны, поэтому позвольте им быть в открытом доступе.
Функциональность одинакова в обоих этих методах. Мы просто проверяем в каждом из них, найден ли соответствующий UIBarButtonItem (кнопка) в элементах панели инструментов, и мы возвращаем соответствующее значение. Итак, вот они оба:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
-(BOOL)isOkayButtonRemoved{
if ([[_toolbar items] indexOfObject:_btnOK] == NSNotFound) {
return YES;
}
else{
return NO;
}
}
-(BOOL)isCancelButtonRemoved {
if ([[_toolbar items] indexOfObject:_btnCancel] == NSNotFound) {
return YES;
}
else{
return NO;
}
}
|
Шаг 5
Далее, давайте реализуем оба -(void)removeOkayButton:(BOOL)shouldRemove
и -(void)removeCancelButton:(BOOL)shouldRemove
. Эти идентичны, как и предыдущие методы. Первая заставляет кнопку Okay представления предупреждений появляться или удаляться из представления, тогда как другая имеет дело с кнопкой Cancel.
Есть одна вещь, на которую я должен обратить внимание. Оба эти метода выполняют одну и ту же работу для разных кнопок, поэтому было бы бессмысленно (и очень плохо) писать процедуру показа / удаления каждой кнопки в / из вида дважды. Поэтому на следующем шаге мы реализуем закрытый метод, который выполняет реальную работу. Его имя -(void)addOrRemoveButtonWithTag:andActionToPerform:
и это то, что мы вызываем в обоих наших текущих методах.
Вот они:
01
02
03
04
05
06
07
08
09
10
11
12
|
-(void)removeOkayButton:(BOOL)shouldRemove{
if ([self isOkayButtonRemoved] != shouldRemove) {
[self addOrRemoveButtonWithTag:OK_BUTTON_TAG andActionToPerform:shouldRemove];
}
}
-(void)removeCancelButton:(BOOL)shouldRemove {
if ([self isCancelButtonRemoved] != shouldRemove) {
[self addOrRemoveButtonWithTag:CANCEL_BUTTON_TAG andActionToPerform:shouldRemove];
}
}
|
Обратите внимание, что в описанных выше методах мы предоставляем приватный метод (еще не реализованный) с shouldRemove
параметра shouldRemove
, и больше ничего не делается в любом из них.
6. Частный метод
Шаг 1
Теперь, когда общедоступные методы реализованы, мы на полпути к месту назначения Кроме того, мы только что увидели, что нам нужно создать другой метод, который не должен быть общедоступным, ответственным за отображение или скрытие каждой кнопки нашего представления предупреждений.
Сначала нам нужно объявить этот метод. Перейдите в приватную часть интерфейса, добавьте выделенную строку и все готово:
1
2
3
|
@interface CustomAlertViewController ()
-(void)addOrRemoveButtonWithTag:(int)tag andActionToPerform:(BOOL)shouldRemove;
@end
|
Шаг 2
Прежде чем мы углубимся в реализацию метода, который мы только что объявили, позвольте мне объяснить, как он будет работать. Сначала мы поместим элементы панели инструментов в изменяемый массив , чтобы иметь возможность добавлять или удалять объекты. Далее, в зависимости от тега кнопки, указанного в параметре, мы будем указывать индекс кнопки в массиве с элементами панели инструментов. Для этой цели мы будем использовать индекс гибкого пространства, который мы добавили в Интерфейсный Разработчик. Если мы собираемся показать или скрыть кнопку «Отмена», то мы хотим получить доступ к индексу 0, в противном случае мы хотим получить доступ к индексу сразу после индекса гибкого пространства.
После того, как у нас есть индекс кнопки в указанном массиве элементов, остальное легко. В зависимости от флага мы либо удаляем кнопку из элементов, либо добавляем ее в соответствующую позицию. Наконец, после того, как вся работа выполнена, мы устанавливаем измененный массив элементов в качестве элементов панели инструментов.
Вот. Обратите внимание на то, что мы используем значения тегов, которые мы ранее определили как константы.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
-(void)addOrRemoveButtonWithTag:(int)tag andActionToPerform:(BOOL)shouldRemove{
NSMutableArray *items = [[_toolbar items] mutableCopy];
int flexSpaceIndex = [items indexOfObject:_flexSpace];
int btnIndex = (tag == OK_BUTTON_TAG) ?
if (shouldRemove) {
[items removeObjectAtIndex:btnIndex];
}
else{
if (tag == OK_BUTTON_TAG) {
[items insertObject:_btnOK atIndex:btnIndex];
}
else{
[items insertObject:_btnCancel atIndex:btnIndex];
}
}
[_toolbar setItems:(NSArray *)items];
}
|
Пришло время объяснить, почему мы использовали свойство strong для свойств btnOk
и btnCancel
IBOutlet. Мы сделали это из-за этого метода. При использовании свойства strong
ссылка на свойство IBOutlet не теряется даже при удалении кнопки с панели инструментов. Это как у нас есть retain
на случай, если мы не будем использовать ARC. Напротив, если мы сохраним свойство weak
, когда мы удаляем кнопку с панели инструментов, ссылка на нее также удаляется. В результате, когда мы снова добавим его на панель инструментов, единственное, что будет найдено, это нулевой объект, а не тот UIBarButtonItem, который нам нужен. Это действительно простое объяснение, и вам следует больше прочитать об этих атрибутах, если вы хотите или должны получить более общие знания об этих вещах. В целях тестирования вы можете изменить свойства в файле CustomAlertViewController.h
на weak
и просмотреть сообщение в отладчике, но только после того, как представление предупреждений будет завершено.
7. Определение протокола
Теперь, когда и открытый, и закрытый метод (ы) готовы, нам нужно определить протокол, который позволяет классу делегата, который его принимает (в нашем случае ViewController
), реализовать необходимые методы, необходимые для обработки нажатий кнопок « ViewController
и «Отмена». ,
Итак, перейдите в файл CustomAlertViewController
и определите протокол вместе со следующими методами делегата:
1
2
3
4
|
@protocol CustomAlertViewControllerDelegate
-(void)customAlertOK;
-(void)customAlertCancel;
@end
|
Затем, сразу после заголовка @interface
, добавьте выделенную строку:
1
2
3
|
@interface CustomAlertViewController : UIViewController
@property (nonatomic, retain) id<CustomAlertViewControllerDelegate> delegate;
…
|
8. Реализация методов IBAction
На данный момент, мы находимся в шаге от того, чтобы подготовить пользовательский вид оповещения. Нам просто нужно реализовать два метода IBAction, которые мы определили ранее. Каждый раз, когда нажимается кнопка Okay, -(void)customAlertOK
метод делегата -(void)customAlertOK
. Аналогично, каждый раз, когда нажимается кнопка «Отмена», -(void)customAlertCancel
метод делегата -(void)customAlertCancel
.
1
2
3
4
5
6
7
|
— (IBAction)btnOkayTap:(id)sender {
[self.delegate customAlertOK];
}
— (IBAction)btnCancelTap:(id)sender {
[self.delegate customAlertCancel];
}
|
9. Подготовьте представление оповещения к действию
Наш новый пользовательский вид наконец готов. Что нам нужно сделать сейчас, так это посмотреть в действии, и вот как мы собираемся попробовать это:
- Когда мы удаляем элемент, появляется уведомление о подтверждении.
- Когда мы используем фиктивный вариант 1, кнопка «Отмена» будет удалена, а «ОК» останется на панели инструментов.
- Когда мы используем фиктивный вариант 2, кнопка «ОК» будет удалена, а «Отмена» останется на панели инструментов.
- Когда мы используем фиктивный вариант 3, обе кнопки «ОК» и «Отмена» будут удалены с панели инструментов, а представление предупреждений исчезнет через несколько секунд.
- Когда мы используем фиктивные опции 4 и 5, кнопка «ОК» останется только на панели инструментов.
Шаг 1
Откройте файл ViewController.h
и импортируйте представление предупреждений:
1
|
#import «CustomAlertViewController.h»
|
Кроме того, сделайте класс ViewController
делегатом CustomAlertViewController
в заголовке интерфейса:
1
2
|
@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, CustomTextInputViewControllerDelegate, AccordionMenuViewControllerDelegate,
CustomAlertViewControllerDelegate>
|
Шаг 2
Переключитесь на файл ViewController.m
и объявите объект CustomAlertViewController
в закрытой части интерфейса (вместе с остальными объектами пользовательских представлений). Также добавьте флаг BOOL с именем isDeletingItem
, который будет указывать, удаляем ли мы элемент из списка или нет:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
@interface ViewController (){
BOOL isEditingItem;
BOOL isDeletingItem;
}
@property (nonatomic, strong) NSMutableArray *sampleDataArray;
@property (nonatomic, strong) NSArray *menuOptionsArray;
@property (nonatomic, strong) CustomTextInputViewController *textInput;
@property (nonatomic, strong) AccordionMenuViewController *accordionMenu;
@property (nonatomic, strong) CustomAlertViewController *customAlert;
@end
|
Шаг 3
Объект и флаг были объявлены, но они еще не были инициализированы. Итак, viewDidLoad
методу viewDidLoad
и добавьте следующие строки перед его закрытием:
1
2
3
4
5
6
7
|
// Initialize the custom alert view controller object
// and set self as its delegate.
_customAlert = [[CustomAlertViewController alloc] init];
[_customAlert setDelegate:self];
// Set the inital value of the isDeleting flag.
isDeletingItem = NO;
|
Шаг 4
Большая часть работы будет выполняться внутри -(void)userSelectedOptionWithIndex:(NSUInteger)index
метод делегата -(void)userSelectedOptionWithIndex:(NSUInteger)index
пользовательского Аккордеонного Меню. Например, когда пользователь выбирает удалить элемент, вместо непосредственного удаления элемента в соответствующем случае внутри метода, мы вызовем пользовательское представление предупреждений, чтобы отобразить подтверждающее сообщение. Точно так же, когда пользователь выбирает любой из других параметров, мы будем показывать соответствующие сообщения с соответствующими видимыми кнопками, как я ранее описал.
Обратите внимание на использование методов removeOkayButton
и removeCancelButton
и на то, как мы с ними играем. Когда мы устанавливаем значение NO
качестве их параметра, соответствующая кнопка удаляется с панели инструментов. Напротив, когда мы устанавливаем значение YES
, соответствующая кнопка снова видна на панели инструментов. Вы также можете видеть, что когда мы показываем пользователю подтверждающее сообщение, флаг isDeletingItem
превращается в YES.
Вот весь метод. Здесь мы заботимся о случае 1 и так далее:
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
-(void)userSelectedOptionWithIndex:(NSUInteger)index{
if (index != [_menuOptionsArray count]) {
NSIndexPath *indexPath = [_table indexPathForSelectedRow];
switch (index) {
case 0:
[_textInput showCustomTextInputViewInView:self.view
withText:[_sampleDataArray objectAtIndex:[indexPath row]]
andWithTitle:@»Edit item»];
// Set the isEditingItem flag value to YES, indicating that
// we are editing an item.
isEditingItem = YES;
break;
case 1:
// Make sure that both the Okay and the Cancel button will be shown on the alert view.
[_customAlert removeOkayButton:NO];
[_customAlert removeCancelButton:NO];
// Show the custom alert view.
[_customAlert showCustomAlertInView:self.view
withMessage:@»Hey, wait!\nAre you sure you want to delete this item?»];
isDeletingItem = YES;
break;
case 2:
// Show only the Okay button and remove the Cancel button.
[_customAlert removeOkayButton:NO];
[_customAlert removeCancelButton:YES];
// Show the custom alert view.
[_customAlert showCustomAlertInView:self.view
withMessage:@»Where is the Cancel button?»];
break;
case 3:
// Show only the Cancel button and remove the Okay button.
[_customAlert removeOkayButton:YES];
[_customAlert removeCancelButton:NO];
// Show the custom alert view.
[_customAlert showCustomAlertInView:self.view
withMessage:@»Where is the Okay button?»];
break;
case 4:
// Remove both of the buttons.
[_customAlert removeOkayButton:YES];
[_customAlert removeCancelButton:YES];
// Show the custom alert view.
[_customAlert showCustomAlertInView:self.view
withMessage:@»This is an alert without buttons.\nThis message will go away in about 3 seconds.»];
[_customAlert performSelector:@selector(removeCustomAlertFromView) withObject:nil afterDelay:3.0];
break;
case 5:
case 6:
// Remove the Cancel button.
[_customAlert removeOkayButton:NO];
[_customAlert removeCancelButton:YES];
// Show the custom alert view.
[_customAlert showCustomAlertInView:self.view
withMessage:@»This is another option of your great menu!»];
break;
default:
break;
}
}
[_accordionMenu closeAccordionMenuAnimated:YES];
}
|
Шаг 5
В качестве последнего шага нам нужно реализовать методы CustomAlertViewController
класса CustomAlertViewController
и добавить в них желаемое поведение демонстрационного приложения. Давайте начнем с -(void)customAlertOK
. В этом методе обратите внимание, что сначала мы проверяем, удаляем ли мы элемент или нет. Если это так, то после выполнения всех необходимых действий по удалению элемента из списка мы немедленно удаляем представление оповещения из родительского представления; в то же время флаг isDeletingItem
снова становится ложным. В противном случае мы просто удаляем представление оповещения из представления.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
-(void)customAlertOK{
if (isDeletingItem) {
NSIndexPath *indexPath = [_table indexPathForSelectedRow];
[_sampleDataArray removeObjectAtIndex:[indexPath row]];
[_table reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];
isDeletingItem = NO;
[_customAlert removeCustomAlertFromViewInstantly];
}
else{
[_customAlert removeCustomAlertFromView];
}
}
|
Следующий метод делегата достаточно прост. Здесь мы также должны проверить isDeletingItem
флага isDeletingItem
и сделать его ложным, на тот случай, если пользователь нажал кнопку «Отмена», чтобы избежать удаления элемента.
1
2
3
4
5
6
7
|
-(void)customAlertCancel{
[_customAlert removeCustomAlertFromView];
if (isDeletingItem) {
isDeletingItem = NO;
}
}
|
Мы готовы! Иди и попробуй в симуляторе. Используйте настраиваемый вид предупреждений как в книжной, так и в альбомной ориентации и наблюдайте, как кнопки работают в каждом конкретном случае.
Вывод
Как мы еще раз доказали, нетрудно создавать собственные представления, используя простые приемы. В этом случае мы создали настраиваемое представление оповещений, многократно используемый компонент, который очень полезен, если кто-то не хочет использовать представление оповещений по умолчанию, предоставляемое iOS. Для целей данного руководства в представление предупреждений были добавлены только две кнопки. Естественно, он может быть обогащен большим количеством кнопок и еще большим количеством функций! Все зависит от вашего воображения и ваших потребностей! Этот урок был последней частью трилогии, в которой были построены три важных, полезных и многократно используемых пользовательских вида. Я надеюсь, что все они служат своему делу и станут полезными инструментами в руках каждого программиста iOS!