Всплывающие окна. Работа с UIPopoverController

Original author: MLS-Automatization
  • Translation
В iPhone SDK 3.2 было добавлено несколько новых элементов интерфейса, таких как UIPopoverController и UISplitViewController.
В этом посте я покажу как пользоваться UIPopoverController.

Для начала, скачайте исходники из моей предыдущей статьи.
Откройте Interface Builder и создайте новый пустой документ.
Выставьте класс File's Owner в ImageScrubberPopupController, добавьте UIView и UIImageView как дочерний элемент UIView.
Сохраните документ и выберите команду «Write class files».
Сохраните класс как ImageScrubberPopupController.

Теперь, пропишите UIViewController родительским классом и добавьте член класса UIImageView * imgView.
Добавьте свойство для этого поля, чтоб получить доступ извне со спецификатором IBOutlet.
Вернитесь в Interface Builder, проведите связи между полем imgView и элементом формы UIImageView и полем view и элементом UIView.

Далее, немного модифицируем ImageScrubberToolbar для корректной работы со всплывающим окном.

UIPopoverController содержит 2 метода для показа всплывающего окна:
  • - (void)presentPopoverFromRect:(CGRect)rect inView:(UIView *)view permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated
  • - (void)presentPopoverFromBarButtonItem:(UIBarButtonItem *)item permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated

Как следует из имён методов, первый показывает всплывающее окно из центра заданного прямоугольника
image

а второй — из кнопки панели, аналогично всплывающему окну в UISplitViewController в портретной ориентации.
image

Мы будем использовать первый метод, поэтому нас нужен прямоугольник выбранной превьюшки, чтоб отобразить всплывающее окно выходящим из неё.
-(CGRect) frameOfSelection
{
  return CGRectMake(self.frame.origin.x + left + SMALL_SIZE*position - SIZE_DIF,
           self.frame.origin.y - LARGE_SIZE,
           LARGE_SIZE,
           LARGE_SIZE);
}


* This source code was highlighted with Source Code Highlighter.

Далее, добавим UIPopoverControllerDelegate к протоколам класса ImageScrubberViewController.
Данный протокол содержит 2 опциональных (не обязательных к реализации) метода:
  • - (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController — вызывается, если пользователь выполнил действие, приводящее к скрытию всплывающего окна. Может возвратить NO для предотвращения скрытия.
  • - (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController — оповещает о скрытии. Метод не вызывается, если -dismissPopoverAnimated: вызван напрямую.

Для создания всплывающего окна, достаточно всего лишь вызвать - (id)initWithContentViewController:(UIViewController *)viewController , передав требуемый для отображения UIViewController. Если необходимо, выставьте также свойство delegate.

Существует одна интересная особенность UIPopoverController.
Если UIViewController с содержимым всплывающего окна является также экземляром класса UINavigationController, всплывающее окно будет иметь широкую верхнюю границу со всеми элементами панели навигации заданного UINavigationController.
image

Чтоб отобразить всплывающее окно, выставьте свойство popoverContentSize и вызовите один из методов: 
  • presentPopoverFromRect: inView: permittedArrowDirections: animated:
  • presentPopoverFromBarButtonItem: permittedArrowDirections: animated:


Если приложение поддерживает несколько ориентаций устройства, необходимо переопределить метод -(void) didRotateFromInterfaceOrientation: для UIViewController.
Если всплывающее окно отображается в момент поворота, необходимо его спрятать и снова показать.
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
  [imageScrubberToolbar rebuild];
  
  if ([popoverController isPopoverVisible])
  {
    [popoverController dismissPopoverAnimated:NO];
    
    CGSize size = [self rotatedSize];
    size.height -= imageScrubberToolbar.frame.size.height;

    popoverController.popoverContentSize = size;
    
    [popoverController presentPopoverFromRect:[imageScrubberToolbar frameOfSelection]
                      inView:self.view
             permittedArrowDirections:UIPopoverArrowDirectionDown
                     animated:YES];
  }
}


* This source code was highlighted with Source Code Highlighter.

При повороте интерфейса высота и ширина UIView НЕ МЕНЯЮТСЯ МЕСТАМИ!
Поэтому добавим метод, возвращающий действительный размер окна.
Если ориентация интерфейса по умолчанию ПОРТРЕТНАЯ, используйте следующий код:
-(CGSize)rotatedSize
{
  if ((self.interfaceOrientation == UIInterfaceOrientationPortrait) ||
    (self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown))
  {
    return self.view.frame.size;
  }
  else
  {
    return CGSizeMake(self.view.frame.size.height, self.view.frame.size.width);
  }
}

* This source code was highlighted with Source Code Highlighter.

Иначе, замените UIInterfaceOrientationPortrait и UIInterfaceOrientationPortraitUpsideDown на UIInterfaceOrientationLandscapeRight и UIInterfaceOrientationLandscapeLeft.

Вот и всё. Мы добавили симпатичное всплывающее окошко к нашей полосе прокрутки.
image
Исходный код можно скачать здесь.
  • +12
  • 6.1k
  • 7
Share post

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 7

    +3
    Спасибо за гайд, особенно за часть отвечающую за смену ориентации:)
      0
      Для меня, не прочитавшего статью, ваш комментарий выглядел двусмысленно.
        0
        Конечно я имел в виду ориентацию интерфейса, а не разработчика :)
      0
      зачем это всё? в документации всё прекрасно описано же.
        0
        для начинающих полезно… и как маленький пиар :)
        0
        спасиба за объединение в одном месте
          0
          если о чём-то хотите прочитать — пишите, если знаю — напишу.

          Only users with full accounts can post comments. Log in, please.