|
Май
21
|
В этом уроке мы узнаем, как добавить в приложение с контроллером навигации “UINavigationController” элемент интерфейса “UIToolbar“. Передо мной стояла задача добавления этой панели в интерфейс одной кнопкой. Щелчок на кнопке должен был загружать контроллер представления, тот же самый что и при выборе “UITableViewCell“. Ниже описано найденное мною решение.
Вот как будет выглядеть готовое приложение:

Для начала создайте новый проект, выбрав опцию “Navigation-Based Application“. Откройте заголовочный файл для “RootViewController” и добавьте переменную типа “UIToolbar” и “UINavigationController“. Вот как в итоге будет выглядеть файл (без комментариев). Одновременно мы создаем еще две переменных того же контроллера “UIViewController” — подробнее на этом моменте мы остановимся ниже.
1 2 3 4 5 6 7 8 9 10 11 12 13 | #import <UIKit/UIKit.h> @class InfoViewController; @interface RootViewController : UITableViewController { UIToolbar *toolbar; InfoViewController *ivControllerToolbar; InfoViewController *ivControllerCell; UINavigationController *infoNavController; } @end |
Откройте реализацию файла и в методе “viewWillAppear” пропишите приведенный ниже код. Это метод всегда вызывается перед появлением представления.
1 2 3 4 5 6 7 8 9 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)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; //Запускаем панель инструментов toolbar = [[UIToolbar alloc] init]; toolbar.barStyle = UIBarStyleDefault; //Устанавливаем панель по ширине окна приложения. [toolbar sizeToFit]; //Вычисляем высоту панели CGFloat toolbarHeight = [toolbar frame].size.height; //Получаем предельные значения для представления верхнего уровня CGRect rootViewBounds = self.parentViewController.view.bounds; //Получаем высоту представления верхнего уровня CGFloat rootViewHeight = CGRectGetHeight(rootViewBounds); //Получаем ширину представления верхнего уровня CGFloat rootViewWidth = CGRectGetWidth(rootViewBounds); //Создаем прямоугольник для панели инструментов CGRect rectArea = CGRectMake(0, rootViewHeight - toolbarHeight, rootViewWidth, toolbarHeight); //Меняем положение и размеры получателя [toolbar setFrame:rectArea]; //Создаем кнопку UIBarButtonItem *infoButton = [[UIBarButtonItem alloc] initWithTitle:@"Info" style:UIBarButtonItemStyleBordered target:self action:@selector(info_clicked:)]; [toolbar setItems:[NSArray arrayWithObjects:infoButton,nil]]; //Добавляем кнопку как subview к контроллеру навигации. [self.navigationController.view addSubview:toolbar]; //Перезагружаем табличное представление [self.tableView reloadData]; } |
Первым шагом инициализируем панель инструментов и рассчитаем ряд значений, определяющих ее положение и высоту/ширину. К панели добавляется вновь созданная кнопка, при щелчке по которой вызывается метод “info_cancel”. Кнопка добавляется через LTR, а после — панель к контроллеру навигации как подпредставление.
В редакторе IB добавьте еще одно представление, которое я назвал “InfoView“. В XCode создайте “UIViewController” с именем “InfoViewController” и назначьте этот класс для использования nib-файлом “InfoView“. В “InfoViewController” задекларируйте свойство Boolean с названием “isViewPushed“, которое будет истиной при помещении представления наверх стека и ложью, когда представление будет модальным. Ориентируясь на величину данной переменной, мы добавим кнопку отмены при загрузке представления в качестве модального.
Вот как будет выглядеть при щелчке информационная кнопка:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | - (void) info_clicked:(id)sender { //Инициализация Info View Controller if(ivControllerToolbar == nil) ivControllerToolbar = [[InfoViewController alloc] initWithNibName:@"InfoView" bundle:[NSBundle mainBundle]]; ivControllerToolbar.isViewPushed = NO; //Инициализация контроллера навигации контроллером info view controller if(infoNavController == nil) infoNavController = [[UINavigationController alloc] initWithRootViewController:ivControllerToolbar]; //Представление контроллера навигации [self.navigationController presentModalViewController:infoNavController animated:YES]; } |
Из заголовочного файла мы знаем, что задекларировано два типа контроллеров “ViewController” для одного nib-файла. Это объясняется тем, что при непредсказуемом поведении результаты одного контроллера представления контролирует одна переменная. При щелчке на информационной кнопке сначала инициализируется “ivControllerToolbar“, потом — “infoNavController” с контроллером представления “ivControllerToolbar“. После представляем “infoNavController” посредством метода “presentModalViewController” из “navigationController“. Если этого не сделать, “infoview” будет загружаться без контроллера навигации, отрезав удобный путь возвращения к “RootViewController“. Обратите внимание, что мы четко сообщаем “infoviewcontroller” о том, что контроллер не помещается в стек. Эта переменная будет использована в относящемся к “InfoViewController” методе “viewDidLoad“.
1 2 3 4 5 6 | if(isViewPushed == NO) { self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancel_Clicked:)] autorelease]; } |
Здесь мы проверяем, чтобы представление попадало в стек только при добавлении кнопки отмены к панели слева. При щелчке на кнопке вызывается метод “cancel_Clicked“, который отменит имеющееся модульное представление. Вот как будет выглядеть код:
1 2 3 4 | -(void) cancel_Clicked:(id)sender { [self.navigationController dismissModalViewControllerAnimated:YES]; } |
Поскольку это табличное представление, выделив строку, пользователь может вызвать для нее детализацию. Вот как будет выглядеть метод “didSelectRowAtIndexPath“:
1 2 3 4 5 6 7 8 9 10 11 12 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // Логика навигации — создаем и помещаем в стек новый контроллер представления //Инициализация контроллера info view. if(ivControllerCell == nil) ivControllerCell = [[InfoViewController alloc] initWithNibName:@"InfoView" bundle:[NSBundle mainBundle]]; ivControllerCell.isViewPushed = YES; //Помещение контроллера представления наверх стека [self.navigationController pushViewController:ivControllerCell animated:YES]; } |
Сначала инициализируем контроллер info view с названием “ivControllerCell“, с помощью которого загружается тот же контроллер представления в методе “didSelectRowAtIndexPath“. В этот раз сообщим контроллеру info view, что представление будет помещено наверх стека.
Это самый простой из найденных мной способов добавить в приложение с “UINavigationController” элемент “UIToolbar“. Удачи!


(2 голосов, средний: 3.50 из 5)
Ноябрь 3rd, 2009 at 13:13
Спасибо большое за статью - то что нужно для работы, сильно помогла.
Единственное, нашёл недостаток, это то что нужно для tableview тоже размер нужно задать - у меня последнюю строка в таблица скрыта тулбаром.