Статьи

iOS SDK: создание пользовательского аккордеонного меню

Из этого туториала вы узнаете, как создать собственное Аккордеонное Меню . Это анимированное меню позволит вам собирать информацию от пользователя в увлекательной и удобной форме. Читайте дальше, чтобы узнать больше!



Начальная позиция аккордеонного меню будет в центре целевого вида, в котором оно появляется. Когда появится меню, его половина переместится к верхней части целевого вида, а другая половина переместится к нижней части вида, расширившись до его полной разрешенной высоты. Во время использования и исходная точка Y, и высота будут изменены, чтобы получить желаемый эффект. Само меню будет состоять из таблицы. Это даст нам большую гибкость в отношении количества опций, добавляемых в меню. Представление таблицы будет существовать как подпредставление в представлении и появится в целевом представлении. Основной вид контроллера представления аккордеонного меню будет работать в качестве прикрытия для подпредставлений, существующих сзади, поэтому пользователь не может нажать на что-либо еще, кроме наших пунктов меню.

Давайте продолжим и воплотим эту идею в жизнь. Вот изображение того, как будет выглядеть конечный продукт.

final_accordion_menu

Первое, что мы должны сделать, это создать новый контроллер вида для нашего аккордеонного меню. До этого мы создадим новую группу в Xcode, чтобы все было аккуратно и аккуратно.

В панели Навигатора проекта на левой стороне XCode, Control + Click (щелчок правой кнопкой мыши) в группе CustomViewsDemo . Выберите опцию New Group из всплывающего меню.

create_group_2

Установите Аккордеонное Меню как имя.

group_name_2

Давайте создадим контроллер представления сейчас. Ctrl + клик (правый клик) в группе меню аккордеона . Выберите опцию New File … из всплывающего меню.

create_file_2

Выберите класс Objective C в качестве шаблона для нового файла и нажмите «Далее».

new_file_template_2

Используйте имя AccordionMenuViewController в поле класса и убедитесь, что в Подклассе поля выбрано значение UIViewController . Не забудьте оставить флажок «С XIB для пользовательского интерфейса» .

accmenu_view_controller

Наконец, нажмите на кнопку «Создать». Убедитесь, что Аккордеонное Меню — это выбранная группа, как показано на следующем изображении.



Первое, что нам нужно сделать с нашим новым контроллером представления, это настроить интерфейс в Интерфейсном Разработчике , который должен быть довольно простым. Большая часть работы будет выполнена в коде.

Нажмите на файл AccordionMenuViewController.xib чтобы включить Интерфейсный Разработчик . Нажмите на представление по умолчанию и отключите функцию Autolayout, чтобы она работала в версиях iOS до 6.

  • Нажмите кнопку Utilities на панели инструментов Xcode, чтобы показать панель Utilites, если она не видна.
  • Нажмите на Инспектора Файлов .
  • Прокрутите немного вниз и нажмите на опцию «Использовать автоматическое расположение», чтобы отключить его.
autolayout_2

Затем перейдите к Инспектору Атрибутов . В разделе Simulated Metrics установите значение Size в None, чтобы оно работало и на 3,5-дюймовом экране.

view_size_2

Идите вперед и добавьте новый вид, но убедитесь, что вы не добавляете его в качестве подпредставления к представлению по умолчанию. Сделайте следующее:

  • Перейдите в раздел « Имитированные метрики » инспектора атрибутов и установите для параметра « Размер» значение « Нет» .
  • Измените цвет фона на темно-серый.
second_view_config

Возьмите табличное представление из библиотеки объектов и добавьте его в качестве подпредставления к представлению, которое мы добавили на предыдущем шаге. Завершите следующую настройку в разделе « Инспектор атрибутов ».

  • Установить Показывает горизонтальные скроллеры в выключенном состоянии.
  • Установить Показывает вертикальные скроллеры в выключенном состоянии.
  • Выключите прокрутку .
  • Измените цвет фона, чтобы очистить.
tableview_options

Вот как должен выглядеть ваш интерфейс на этом этапе.

ib_sample_2

Далее мы собираемся создать два свойства IBOutlet для дополнительного представления и представления таблицы, которые мы добавили в проект ранее. Во-первых, мы должны сделать так, чтобы появился помощник редактора . Нажмите среднюю кнопку в разделе редактора на панели инструментов Xcode, чтобы открыть ее.

assistant_editor2_1

Чтобы подключить представление к новому свойству IBOutlet , выберите «Показать структуру документа»> «Control + щелчок (щелчок правой кнопкой мыши)»> «Новый источник ссылок» . Перетащите в помощник редактора .

insert_outlet_2

Я назвал свойство viewAccordionMenu и рекомендую использовать то же имя, чтобы избежать проблем при кодировании. Установите для параметра « Хранилище» значение « Сильный» вместо значения по умолчанию « Слабое»

iboutlet_name_2

Теперь давайте добавим свойство IBOutlet для таблицы. Как и выше, создайте новое свойство с именем tblAccordionMenu . Также установите для параметра Storage значение Strong .

Вот два свойства IBOutlet .

1
2
@property (strong, nonatomic) IBOutlet UIView *viewAccordionMenu;
@property (strong, nonatomic) IBOutlet UITableView *tblAccordionMenu;

Все идет нормально! Мы создали контроллер представления для аккордеонного меню, настроили интерфейс и создали два обязательных свойства IBOutlet для представлений, которые мы добавили в конструктор. Теперь пришло время начать писать код.

Прежде всего, мы должны установить наш контроллер представления как делегат и источник данных для представления таблицы, которое мы создали в Интерфейсном Разработчике . Наш контроллер представления должен принять соответствующие протоколы. Нажмите на файл AccordionMenuViewController.h и рядом с заголовком @interface добавьте следующее.

1
@interface AccordionMenuViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>

Нажмите на файл AccordionMenuViewController.m и реализуйте простой метод init . Установите контроллер представления в качестве делегата и источника данных табличного представления.

1
2
3
4
5
6
7
8
9
-(id)init{
    self = [super init];
    if (self) {
        [_tblAccordionMenu setDelegate:self];
        [_tblAccordionMenu setDataSource:self];
    }
     
    return self;
}

Чтобы меню выглядело лучше, давайте добавим рамку. В init добавьте выделенный код.

01
02
03
04
05
06
07
08
09
10
if (self) {
        [_tblAccordionMenu setDelegate:self];
        [_tblAccordionMenu setDataSource:self];
         
        // Add some border around the tableview.
        [[_tblAccordionMenu layer] setBorderColor:[UIColor whiteColor].CGColor];
        [[_tblAccordionMenu layer] setBorderWidth:2.0];
    }

Обязательно добавьте это в начало файла.

1
#import <QuartzCore/QuartzCore.h>

Установите цвет фона для вида по умолчанию светло-серый с прозрачностью.

1
2
3
4
5
6
if (self) {
        …
        [self.view setBackgroundColor:[UIColor colorWithRed:0.33 green:0.33 blue:0.33 alpha:0.75]];
    }

Это хорошая идея, чтобы определить высоту строки таблицы как константу. Помимо tableView:heightForRowAtIndexPath , мы будем использовать его в других методах. Сразу после команд #import добавьте следующее.

1
#define ROW_HEIGHT 40.0 // The height of each option of the accordion menu.

Аккордеонное меню будет использовать анимацию, чтобы появляться и исчезать. Мы можем установить продолжительность анимации как постоянную.

1
#define ANIMATION_DURATION 0.25 // The duration of the animation.

С этого момента, если мы хотим изменить высоту строки или продолжительность анимации, мы сделаем это один раз без изменения значений в каждом методе.

Мы должны объявить две частные переменные и NSArray . Переменные определяют ширину и высоту меню аккордеона, то есть ширину и высоту родительского представления нашего табличного представления. NSArray — это массив, в котором будут храниться пункты меню, и он будет источником данных таблицы.

Вверху файла AccordionMenuViewController.m добавьте следующие строки в раздел @interface .

1
2
3
4
5
6
7
8
@interface AccordionMenuViewController (){
    CGFloat menuViewWidth;
    CGFloat menuViewHeight;
}
 
@property (nonatomic, strong) NSArray *optionsArray;
 
@end

Убедитесь, что вы не забыли фигурные скобки!


Существует как минимум три открытых метода, которые должны быть реализованы, чтобы меню аккордеона работало правильно. Первый метод будет использоваться для установки параметров меню, второй метод заставит меню аккордеона появиться, и третий метод заставит его исчезнуть.

Прежде всего, мы должны объявить методы, которые я упомянул выше, в файл .h . Итак, нажмите на файл AccordionMenuViewController.h и добавьте следующее.

1
2
3
-(void)setMenuOptions:(NSArray *)options;
-(void)showAccordionMenuInView:(UIView *)targetView;
-(void)closeAccordionMenuAnimated:(BOOL)animated;

Давайте реализуем первый метод. Нажмите на файл AccordionMenuViewController.m и напишите или скопируйте / вставьте следующий код.

1
2
3
4
5
6
-(void)setMenuOptions:(NSArray *)options{
    NSMutableArray *tempArray = [NSMutableArray arrayWithArray:options];
    [tempArray addObject:@»Close»];
     
    _optionsArray = [[NSArray alloc] initWithArray:(NSArray *)tempArray copyItems:YES];
}

Хотя это действительно простой метод, позвольте мне объяснить его немного. Мне и пользователю и программисту легче предоставлять массив только с опциями меню. Вам не нужно беспокоиться о так называемой опции закрытия меню . Это действительно полезно только тогда, когда кто-то собирается использовать аккордеонное меню более чем в одном случае. Я использую изменяемый массив tempArray для объединения как пользовательских параметров, так и параметров закрытия. Если вы знаете, что _optionsArray не является изменяемым, вы поймете, что он не может принимать новые объекты после создания. Я инициализирую массив _optionsArray . По вашему выбору следует избегать использования этой логики или изменять заголовок опции закрытия меню.

Давайте перейдем к следующему методу. Это касается способа отображения меню аккордеона на экране. В нем происходит много разных шагов, поэтому я буду представлять и обсуждать его по частям.

Прежде всего, нам нужно принять во внимание строку состояния, когда должно появиться меню аккордеона. Это потому, что мы будем использовать целевой вид, где появится меню и его рамку, в качестве основы для настройки наших видов. Таким образом, очень важно правильно обрабатывать строку состояния. Если строка состояния скрыта, проблем нет вообще. Однако, если он виден, при создании нашего представления будет создано пустое пространство, равное высоте строки состояния. Итак, в качестве первого шага нам нужно проверить, видна ли строка состояния, и сохранить ее высоту, чтобы исправить смещение, созданное этим.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
-(void)showAccordionMenuInView:(UIView *)targetView{
    // STEP 1: THE STATUS BAR OFFSET
    CGFloat statusBarOffset;
     
    if (![[UIApplication sharedApplication] isStatusBarHidden]) {
        CGSize statusBarSize = [[UIApplication sharedApplication] statusBarFrame].size;
        if (statusBarSize.width < statusBarSize.height) {
            statusBarOffset = statusBarSize.width;
        }
        else{
            statusBarOffset = statusBarSize.height;
        }
    }
    else{
        statusBarOffset = 0.0;
    }

Это подход, который мы использовали во время предыдущего урока в пользовательском представлении ввода текста.

Далее мы должны указать, какая ширина и высота целевого вида зависит от ориентации. Опять же, в зависимости от ориентации, мы должны «сказать», смещение, которое должно быть перемещено нашим представлением по умолчанию, по оси X или Y.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-(void)showAccordionMenuInView:(UIView *)targetView{
    …
    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;
    }
   …

Следующий шаг прост. Мы просто настроим представление по умолчанию self.view , установив его фрейм и соответствующее смещение, его альфа-значение и, наконец, добавив его в качестве подпредставления к целевому представлению.

1
2
3
4
5
6
7
8
9
-(void)showAccordionMenuInView:(UIView *)targetView{
    …
    // STEP 3 : SETUP THE SELF.VIEW
     
    [self.view setFrame:CGRectMake(targetView.frame.origin.x, targetView.frame.origin.y, width, height)];
    [self.view setFrame:CGRectOffset(self.view.frame, offsetX, offsetY)];
    [self.view setAlpha:0.0];
    [targetView addSubview:self.view];
    …

Теперь пришло время настроить представление, которое содержит представление таблицы. Мы должны указать его размер здесь, имея в виду, что он будет занимать часть экрана. Я установил его ширину 260.0 пикселей , но вы можете изменить его в соответствии с вашими желаниями. Его высота будет рассчитываться на основе общих параметров и высоты каждой строки. Это означает, что высота будет равна сумме строк, умноженной на высоту каждой строки. В случае слишком большого количества параметров и высоты меню, превышающей высоту целевого вида в любой ориентации, мы должны вручную уменьшить меню и включить прокрутку в виде таблицы. Чтобы достичь этого, мы будем использовать временную переменную, которая будет сохранять высоту в каждом случае.

Чтобы добиться эффекта аккордеона, нам нужно установить его кадр дважды. Сначала мы дадим ему нормальный кадр и отцентрируем его в соответствии с центральной точкой целевого вида. Затем мы сохраним исходную точку Y и снова установим кадр. Мы сделаем это, установив исходную точку Y в исходную точку Y своего центра и установив ее высоту в 0.0. Когда точка начала Y и высота вернутся к своим первоначальным значениям, мы получим отличный эффект аккордеона.

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
-(void)showAccordionMenuInView:(UIView *)targetView{
    …
    // STEP 4: SETUP THE MENU VIEW
     
    menuViewWidth = 260.0;
    // The height is the height of each row multiplied by the number
    // of options.
    menuViewHeight = ROW_HEIGHT * [_optionsArray count];
     
    // Declare and use a local, temporary variable for the height of the menu view.
    CGFloat tempMenuHeight;
    if (menuViewHeight > height) {
        // If the menuViewHeight as set above is greater than the height of the target view
        // then set the menu view’s height to targetview’s height — 50.0.
        // Also enable scrolling on tableview.
        tempMenuHeight = height — 50.0;
        [_tblAccordionMenu setScrollEnabled:YES];
    }
    else{
        // Otherwise if the menu view height is not greater than the targetView’s height
        // then the tempMenuHeight simply equals to the menuViewHeight.
        // The scrolling doesn’t have to be enabled.
        tempMenuHeight = menuViewHeight;
        [_tblAccordionMenu setScrollEnabled:NO];
    }
     
    // Set the initial frame of the menu view.
    // interested in the x and y origin points because they’ll be automatically
    // set right after, so set it to 0.0.
    [_viewAccordionMenu setFrame:CGRectMake(0.0, 0.0, menuViewWidth, tempMenuHeight)];
     
    // Set its center to the self.view’s center.
    [_viewAccordionMenu setCenter:self.view.center];
     
    // Store temporarily the current y origin point of the menu view.
    CGFloat yPoint = _viewAccordionMenu.frame.origin.y;
    // Now set the center.y point as the y origin point of the menu view and its height to 0.0.
    [_viewAccordionMenu setFrame:CGRectMake(_viewAccordionMenu.frame.origin.x, _viewAccordionMenu.center.y, _viewAccordionMenu.frame.size.width, 0.0)];
    // Add the menu view to the targetView view.
    [targetView addSubview:_viewAccordionMenu];
    …

Пришло время оживить меню. Здесь действительно нечего обсуждать. Мы просто меняем альфа-значение self.view и устанавливаем последний кадр в меню.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
-(void)showAccordionMenuInView:(UIView *)targetView{
    …
    // STEP 5: ANIMATE
    [UIView beginAnimations:@»» context:nil];
    [UIView setAnimationDuration:ANIMATION_DURATION];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
     
    [self.view setAlpha:0.5];
     
    // Set the yPoint value as the y origin point of the menu view
    // and the tempMenuHeight value as its height.
    [_viewAccordionMenu setFrame:CGRectMake(_viewAccordionMenu.frame.origin.x,
                                            yPoint,
                                            _viewAccordionMenu.frame.size.width,
                                            tempMenuHeight)];
     
    [UIView commitAnimations];
    …

Наконец, перезагрузите данные таблицы, чтобы опции меню появились в виде таблицы. Обратите внимание, что метод заканчивается здесь.

1
2
3
4
5
6
-(void)showAccordionMenuInView:(UIView *)targetView{
    …
    // STEP 6: RELOAD THE TABLEVIEW DATA
    [_tblAccordionMenu reloadData];
    …
}

Давайте напишем следующий метод относительно закрытия меню. Там нет ничего, что мне действительно нужно упомянуть здесь. Я только подчеркну, что он использует логический параметр, который указывает, нужно ли анимировать закрытие или нет.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
-(void)closeAccordionMenuAnimated:(BOOL)animated{
    if (animated) {
        [UIView beginAnimations:@»» context:nil];
        [UIView setAnimationDuration:ANIMATION_DURATION];
        [UIView setAnimationCurve:UIViewAnimationCurveLinear];
         
        [self.view setAlpha:0.0];
         
        [_viewAccordionMenu setFrame:CGRectMake(_viewAccordionMenu.frame.origin.x, _viewAccordionMenu.center.y, _viewAccordionMenu.frame.size.width, 0.0)];
         
        [UIView commitAnimations];
         
        [_viewAccordionMenu performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:ANIMATION_DURATION + 0.5];
        [self.view performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:ANIMATION_DURATION + 0.5];
    }
    else{
        [_viewAccordionMenu removeFromSuperview];
        [self.view removeFromSuperview];
    }
}

Нам удалось правильно отобразить наше меню при вызове. Что происходит, когда пользователь поворачивает устройство? Ничего! Это потому, что мы ничего не написали об этом, поэтому давайте сделаем это сейчас. Мы реализуем метод viewWillLayoutSubviews , который viewWillLayoutSubviews при каждом изменении ориентации. Вы можете прочитать больше об этом на сайте разработчика Apple .

Вот краткая версия того, что мы собираемся сделать. Сначала мы установим рамку представления меню на основе переменных menuViewWidth и menuViewHeight мы установили ранее. Мы будем центрировать его в соответствии с центральной точкой self.view . Далее, в зависимости от ориентации устройства, мы рассчитаем высоту суперпредставления. Наконец, мы проверим, больше ли высота представления, чем высота суперпредставления. Если это так, мы вручную уменьшим его и -(void)showAccordionMenuInView:(UIView *)targetView прокрутку, как мы это делали в -(void)showAccordionMenuInView:(UIView *)targetView . В противном случае мы просто выключим прокрутку.

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
-(void)viewWillLayoutSubviews{
    // Get the current orientation.
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
     
    // Set the menu view frame and center it.
    [_viewAccordionMenu setFrame:CGRectMake(_viewAccordionMenu.frame.origin.x,
                                            _viewAccordionMenu.frame.origin.y,
                                            menuViewWidth,
                                            menuViewHeight)];
     
    [_viewAccordionMenu setCenter:self.view.center];
     
     
    // Get the superview’s height.
    CGFloat height;
    if (orientation == UIInterfaceOrientationLandscapeLeft ||
        orientation == UIInterfaceOrientationLandscapeRight) {
        height = self.view.superview.frame.size.width;
    }
    else{
        height = self.view.superview.frame.size.height;
    }
     
     
    // Check if the menu view’s height is greater than the superview’s height.
    if (_viewAccordionMenu.frame.size.height > height) {
        // If that’s true then set the menu view’s frame again by setting its height
        // to superview’s height minus 50.0.
        [_viewAccordionMenu setFrame:CGRectMake(_viewAccordionMenu.frame.origin.x,
                                                _viewAccordionMenu.frame.origin.y,
                                                menuViewWidth,
                                                height — 50.0)];
        // Center again.
        [_viewAccordionMenu setCenter:self.view.center];
         
        // Also allow scrolling.
        [_tblAccordionMenu setScrollEnabled:YES];
    }
    else{
        // In that case the menu view’s height is not greater than the superview’s height
        // so set scrolling to NO.
        [_tblAccordionMenu setScrollEnabled:NO];
    }
}

Вот минимально необходимые методы, необходимые для работы таблицы. Обратите внимание, что в -(UITableViewCell *)tableView:cellForRowAtIndexPath: метод, мы проверим, является ли текущая строка последней или нет.

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
-(int)numberOfSectionsInTableView:(UITableView *)tableView{
    return 1;
}
 
-(int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [_optionsArray count];
}
 
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *CellIdentifier = @»Cell»;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
     
    if ([indexPath row] < [_optionsArray count] — 1) {
        [[cell contentView] setBackgroundColor:[UIColor colorWithRed:204.0/255.0 green:204.0/255.0 blue:204.0/255.0 alpha:1.0]];
        [[cell textLabel] setTextColor:[UIColor blackColor]];
        [[cell textLabel] setShadowColor:[UIColor whiteColor]];
        [[cell textLabel] setShadowOffset:CGSizeMake(1.0, 1.0)];
    }
    else{
        [[cell contentView] setBackgroundColor:[UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:104.0/255.0 alpha:1.0]];
        [[cell textLabel] setTextColor:[UIColor whiteColor]];
        [[cell textLabel] setShadowColor:[UIColor blackColor]];
        [[cell textLabel] setShadowOffset:CGSizeMake(1.0, 1.0)];
    }
     
     
    [[cell textLabel] setFont:[UIFont fontWithName:@»Georgia» size:17.0]];
     
    [cell setSelectionStyle:UITableViewCellSelectionStyleGray];
     
     
    CGRect rect = CGRectMake(0.0, 0.0, self.view.bounds.size.width, [self tableView:tableView heightForRowAtIndexPath:indexPath]);
    [[cell textLabel] setFrame:rect];
    [[cell textLabel] setTextAlignment:NSTextAlignmentCenter];
    [[cell textLabel] setText:[_optionsArray objectAtIndex:[indexPath row]]];
     
     
    return cell;
}
 
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return ROW_HEIGHT;
}

Нам также нужно обработать постукивание по строкам таблицы. Обратите внимание в следующем методе, что мы удаляем выделение из строки постукивания.

1
2
3
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [[tableView cellForRowAtIndexPath:indexPath] setSelected:NO];
}

Мы скоро вернемся к этому методу.


Когда пользователь нажимает на строку или, другими словами, на пункт меню, мы хотим, чтобы контроллер представления вызывающей стороны был уведомлен о выбранном выборе.

Нажмите на файл AccordionMenuViewController.h и напишите следующий код прямо перед заголовком @interface .

1
2
3
@protocol AccordionMenuViewControllerDelegate
-(void)userSelectedOptionWithIndex:(NSUInteger)index;
@end

Теперь объявите свойство делегата.

01
02
03
04
05
06
07
08
09
10
11
@interface AccordionMenuViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) id<AccordionMenuViewControllerDelegate> delegate;
 
@property (strong, nonatomic) IBOutlet UIView *viewAccordionMenu;
@property (strong, nonatomic) IBOutlet UITableView *tblAccordionMenu;
 
-(void)setMenuOptions:(NSArray *)options;
-(void)showAccordionMenuInView:(UIView *)targetView;
-(void)closeAccordionMenuAnimated:(BOOL)animated;
 
@end

Когда следует использовать userSelectedOptionWithIndex делегата userSelectedOptionWithIndex ? Каждый раз, когда выбирается пункт меню. Вернитесь в -(void)tableView:didSelectRowAtIndexPath: метод и добавьте следующие строки.

1
2
3
4
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [[tableView cellForRowAtIndexPath:indexPath] setSelected:NO];
    [self.delegate userSelectedOptionWithIndex:[indexPath row]];
}

Меню аккордеона теперь готово. Пришло время увидеть это в действии. Сделайте необходимые приготовления в классе ViewController .

Прежде всего, класс ViewController должен принять протокол AccordionMenuViewControllerDelegate . Откройте файл ViewController.h , импортируйте класс AccordionMenuViewController.h и добавьте протокол в заголовок @interface .

1
2
3
4
5
#import <UIKit/UIKit.h>
#import «CustomTextInputViewController.h»
#import «AccordionMenuViewController.h»
 
@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, CustomTextInputViewControllerDelegate, AccordionMenuViewControllerDelegate>

Откройте файл ViewController.m и перейдите к закрытой части @interface вверху файла. Там добавьте NSArray, который будет использоваться для опций, которыми мы будем предоставлять меню аккордеона, а также объект AccordionMenuViewController .

1
2
3
4
5
6
@interface ViewController (){
@property (nonatomic, strong) NSArray *menuOptionsArray;
@property (nonatomic, strong) AccordionMenuViewController *accordionMenu;
 
@end

Внутри метода viewDidLoad нам нужно инициализировать как массив, так и объект, который мы объявили на предыдущем шаге.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
— (void)viewDidLoad
{
    [super viewDidLoad];
    …
    // Set the options that will appear in the accordion menu.
    _menuOptionsArray = [[NSArray alloc] initWithObjects:@»Edit»,
                         @»Delete»,
                         @»Option 1″,
                         @»Option 2″,
                         @»Option 3″,
                         @»Option 4″,
                         @»Option 5″,
                         nil];
     
    // Init the accordion menu view controller.
    _accordionMenu = [[AccordionMenuViewController alloc] init];
    // Set self as its delegate.
    [_accordionMenu setDelegate:self];
    // Set the menu options.
    [_accordionMenu setMenuOptions:_menuOptionsArray];
}

Мы будем использовать только два варианта из списка выше. Пока что остальные предназначены только для демонстрации.

Перейдите к -(void)tableView:didSelectRowAtIndexPath: метод и добавьте следующее.

1
2
// Make the accordion menu appear.
[_accordionMenu showAccordionMenuInView:self.view];

Если вы продолжаете проект из предыдущего урока, удалите или закомментируйте любой существующий контент.

Наконец, нам просто нужно реализовать метод делегата -(void)userSelectedOptionWithIndex:(NSUInteger)index . Это где любые действия предпринимаются, когда пользователь нажимает на пункты меню.

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
-(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:
                [_sampleDataArray removeObjectAtIndex:[indexPath row]];
                [_table reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];
                break;
                 
            default:
                break;
        }
    }
     
    [_accordionMenu closeAccordionMenuAnimated:YES];
}

Мы закончили! Запустите приложение на симуляторе или на устройстве и проверьте меню. Поиграйте с ним, и не стесняйтесь улучшать его или менять в соответствии с вашими потребностями.


Предоставление пользователям пунктов меню, которые отличаются от обычных предопределенных, всегда является большой проблемой для программиста. Как вы теперь знаете, мы можем добиться хорошего результата без использования каких-либо сложных или экстремальных приемов. Аккордеонное меню, представленное в этом уроке, является довольно приятным способом отображения опций для пользователя и, самое главное, его можно использовать повторно. Я надеюсь, что он станет полезным инструментом для всех, кто его использует!