Статьи

iOS SDK: настройка всплывающих окон

Popovers — отличный способ отобразить дополнительную информацию в приложении для iPad. Неизбежно, как и с большинством объектов iOS, небольшая настройка имеет большое значение при создании уникального дизайна, который вписывается в ваше собственное приложение. В этом руководстве мы создадим базовый поповер, а затем рассмотрим настройки по одной за раз, предоставляя вам простой путь реализации настроек в вашем собственном приложении.


Запустите Xcode и выберите « Файл»> «Создать»> «Проект», чтобы создать новый проект. Выберите приложение iOS Single View и нажмите « Далее» .

фигура 1
фигура 1

Заполните текстовые поля названием проекта, названием организации и идентификатором компании. Выберите iPad в раскрывающемся списке « Устройства» и убедитесь, что установлен флажок « Использовать автоматический подсчет ссылок» . Оставьте флажки для Использовать раскадровки и Включить юнит-тесты снятыми и нажмите Далее . Выберите место для сохранения вашего файла и нажмите « Создать» .

фигура 2
фигура 2

Давайте используем контроллер навигации, чтобы добавить кнопку для отображения всплывающего окна. Нажмите на AppDelegate.m и найдите application:didFinishLaunchingWithOptions: метод. Добавьте следующий код для создания контроллера навигации и установите его в качестве корневого контроллера представления.

1
2
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = navController;

Теперь мы можем добавить кнопку «плюс» на панель навигации. Нажмите на ViewController.m и добавьте следующий код в метод viewDidLoad чуть ниже [super viewDidLoad]; ,

1
2
3
4
5
6
UIBarButtonItem *popoverButton = [[UIBarButtonItem alloc]
 
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
                     target:self
                     action:@selector(showPopover:)];
self.navigationItem.rightBarButtonItem = popoverButton;

UIBarButtonSystemItemAdd создает кнопку «плюс»; мы добавим его в правую часть панели навигации. Далее мы реализуем метод showPopover: используемый в качестве селектора.


Перед реализацией метода showPopover: давайте добавим свойство для контроллера popover. Нажмите на файл ViewController.h и добавьте следующее свойство.

1
@property (nonatomic, strong) UIPopoverController *popController;

Вернитесь к файлу ViewController.m и объявите showPopover: метод в расширении класса, как показано ниже.

1
2
3
@interface ViewController ()
— (void)showPopover:(id)sender;
@end

Добавьте следующий код, чтобы определить метод в @implementation .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
— (void)showPopover:(id)sender
{
    if (self.popController.popoverVisible) {
        [self.popController dismissPopoverAnimated:YES];
        return;
    }
 
    UIViewController *contentViewController = [[UIViewController alloc] init];
    contentViewController.view.backgroundColor = [UIColor yellowColor];
    UIPopoverController *popController = [[UIPopoverController alloc] initWithContentViewController:contentViewController];
    popController.popoverContentSize = CGSizeMake(300.0f, 600.0f);
    self.popController = popController;
    [self.popController presentPopoverFromBarButtonItem:sender
                    permittedArrowDirections:UIPopoverArrowDirectionUp
                                    animated:YES];
}

Сначала мы проверяем, отображается ли уже всплывающее окно на экране. Если это видно, всплывающее окно отклоняется, и метод возвращается. Если всплывающее окно не отображается на экране, мы создаем контроллер представления для отображения в всплывающем окне. Затем мы создаем контроллер popover и устанавливаем его размер. Последняя строка кода сообщает контроллеру всплывающих окон о необходимости нажимать кнопку на панели навигации — в этом случае кнопка «плюс» и позволяет направлению стрелки указывать только вверх. Одним из преимуществ использования этого метода является то, что, если пользователь нажимает другую кнопку на панели навигации, касание передается на панель навигации.


На данный момент мы внедрили стандартный поповер. Создайте и запустите свой проект и коснитесь кнопки «плюс», чтобы увидеть основной поповер. Давайте посмотрим на основы настройки его внешнего вида.


Чтобы настроить внешний вид всплывающего окна, нам нужно UIPopoverBackgroundView подкласс UIPopoverBackgroundView . Нажмите « Файл»> «Создать»> «Файл» , выберите класс «Какао iOS Touch Objective-C» и нажмите « Далее» .

Рисунок 3
Рисунок 3

Назовите класс PopoverBackgroundView и выберите UIPopoverBackgroundView из подкласса раскрывающегося UIPopoverBackgroundView .

Рисунок 4
Рисунок 4

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

1
2
@synthesize arrowDirection = _arrowDirection;
@synthesize arrowOffset = _arrowOffset;

Есть три метода класса, которые должны быть переопределены. Давайте определим некоторые значения для использования с методами.

1
2
3
#define kArrowBase 30.0f
#define kArrowHeight 20.0f
#define kBorderInset 8.0f

Добавьте приведенный ниже код для переопределения arrowBase , arrowHeight и contentViewInsets .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
+ (CGFloat)arrowBase
{
    return kArrowBase;
}
 
+ (CGFloat)arrowHeight
{
    return kArrowHeight;
}
 
+ (UIEdgeInsets)contentViewInsets
{
    return UIEdgeInsetsMake(kBorderInset, kBorderInset, kBorderInset, kBorderInset);
}

Метод arrowBase определяет ширину основания стрелки, а метод arrowHeight определяет высоту стрелки. Метод contentViewInsets указывает, как далеко от края фона отображается содержимое.

Давайте добавим фоновый цвет, чтобы мы могли ясно видеть различные части. Добавьте следующий код в оператор if в методе initWithFrame:

1
self.backgroundColor = [UIColor grayColor];

Прежде чем мы сможем протестировать popover, нам нужно импортировать и установить свойство класса фонового представления popover контроллера popover. Нажмите на файл ViewController.m и импортируйте заголовочный файл всплывающего окна, как показано ниже.

1
#import «PopoverBackgroundView.h»

Пока мы все еще в файле ViewController.m , добавьте следующую строку кода чуть ниже, где мы создали UIPopoverController в showPopover:

1
popController.popoverBackgroundViewClass = [PopoverBackgroundView class];

Создайте и запустите проект и нажмите кнопку «плюс», чтобы увидеть всплывающее окно. Вы можете видеть, что стандартный popover был заменен настройками, которые мы добавили до сих пор. Серая рамка вокруг всплывающего окна показывает вставки, возвращенные методом contentViewInsets . Вы можете отрегулировать вставки по мере необходимости для достижения желаемого вида. Мы нарисуем стрелку позже в уроке для отображения на экране.


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

1
2
3
4
+ (BOOL)wantsDefaultContentAppearance
{
    return NO;
}

Создайте и запустите проект, и вы сможете увидеть разницу.


Нам нужно создать стрелку и управлять ею самим; Давайте объявим свойство для представления изображения, которое будет отображать стрелку. Добавьте следующий код в расширение класса.

1
@property (nonatomic, strong) UIImageView *arrowImageView;

Теперь мы можем создать экземпляр изображения. Замените код внутри оператора if в initWithFrame: следующим кодом.

1
2
3
4
5
self.backgroundColor = [UIColor clearColor];
 
UIImageView *arrowImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
self.arrowImageView = arrowImageView;
[self addSubview:self.arrowImageView];

Давайте изменим вставку границы, обновив kBorderInset определенный в PopoverBackgroundView.m, с помощью следующего кода.

1
#define kBorderInset 0.0f

Чтобы нарисовать стрелку, нам нужно объявить метод для рисования. Добавьте следующее объявление метода в расширение класса в PopoverBackgroundView.m .

1
— (UIImage *)drawArrowImage:(CGSize)size;

Теперь добавьте определение метода в @implementation .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
— (UIImage *)drawArrowImage:(CGSize)size
{
    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [[UIColor clearColor] setFill];
    CGContextFillRect(ctx, CGRectMake(0.0f, 0.0f, size.width, size.height));
 
    CGMutablePathRef arrowPath = CGPathCreateMutable();
    CGPathMoveToPoint(arrowPath, NULL, (size.width/2.0f), 0.0f);
    CGPathAddLineToPoint(arrowPath, NULL, size.width, size.height);
    CGPathAddLineToPoint(arrowPath, NULL, 0.0f, size.height);
    CGPathCloseSubpath(arrowPath);
    CGContextAddPath(ctx, arrowPath);
    CGPathRelease(arrowPath);
 
    UIColor *fillColor = [UIColor yellowColor];
    CGContextSetFillColorWithColor(ctx, fillColor.CGColor);
    CGContextDrawPath(ctx, kCGPathFill);
 
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
 
}

Вместо того, чтобы использовать импортированное изображение, код выше программно создает стрелку.

При каждом изменении границ подкласса фонового представления всплывающего окна кадр стрелки необходимо пересчитывать. Мы можем сделать это путем переопределения layoutSubviews . Добавьте следующий код в PopoverBackgroundView.m .

01
02
03
04
05
06
07
08
09
10
— (void)layoutSubviews
{
    [super layoutSubviews];
 
    CGSize arrowSize = CGSizeMake([[self class] arrowBase], [[self class] arrowHeight]);
 
    self.arrowImageView.image = [self drawArrowImage:arrowSize];
 
    self.arrowImageView.frame = CGRectMake(((self.bounds.size.width — arrowSize.width) kBorderInset), 0.0f, arrowSize.width, arrowSize.height);
}

Рамка вида изображения стрелки и изображения стрелки рассчитываются на основе границ фонового представления всплывающего окна, вставок границы, а также основания и высоты стрелки.


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


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