Войти

Или войди с помощью

Разработка Всплывающие сообщения для iOS

Разработка
Никита Narmo Дёнин avatar |
Всплывающие сообщения для iOS

Для отображения всплывающих сообщений в iOS есть только один компонент — UIAlertView. Им очень удобно пользоваться, ведь создать и отобразить его можно буквально двумя-тремя строчками кода. Но у него есть один изъян: он блокирует интерфейс до того момента, пока пользователь не нажмёт кнопку, чтобы принудительно скрыть его. А иногда программисту всего лишь нужно показать какое-либо информационное сообщение, не требующее от пользователя никаких действий. В Android это решено с помощью компонента Toast, в который передаётся текст сообщения (а при необходимости и координаты, в которых оно должно отобразиться).

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

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

Вот задачи, которые я возложил на свой «тостер»:

– отобразить сообщение с анимацией
– подождать 1 секунду
– скрыть сообщение с анимацией

Я сконструировал объект-тостер так, чтобы он создавался и отображался одной строчкой кода:

[WToast showWithText:text];

После вызова этого метода объект сам контролирует своё поведение (появление, ожидание и скрытие). Прежде всего нам надо создать текстовую метку, которая и будет содержать наш текст. Так как текст может быть любой длины, придётся динамически обсчитывать размеры создаваемого компонента UILabel. Для этого в фреймворке UIKit есть специальный метод для объектов NSString, позволяющий узнать размеры текста при заданных шрифте, ширине и типе переноса строк.

Итак, создаём объект UILabel и вычисляем размеры текста:

UILabel *textLabel = [[UILabel alloc] init];
textLabel.backgroundColor = [UIColor clearColor];
textLabel.textAlignment = UITextAlignmentCenter;
textLabel.font = [UIFont systemFontOfSize:14];
textLabel.textColor = RGB(255, 255, 255);
textLabel.numberOfLines = 0;
textLabel.lineBreakMode = UILineBreakModeWordWrap;
CGSize sz = [text sizeWithFont:textLabel.font constrainedToSize:CGSizeMake(width - 20.0f, 9999.0f) lineBreakMode:textLabel.lineBreakMode];

Свойство numberOfLines, выставленное в 0, указывает метке, что количество строк в ней не ограничено. Свойство lineBreakMode сообщает, что при достижении правой границы будет происходить перенос по словам (это нужно, чтобы окончание строки не превратилось в многоточие). В методе -sizeWithFont:constrainedToSize:lineBreakMode: параметр constrainedToSize указывает максимальный размер будущей текстовой метки. Передав туда высоту 9999 пикселей, я гарантировано получу метку без многоточий в конце строки (ведь высота экрана iPhone составляет всего 480 пикселей).

Теперь нужно создать контейнер WToast (который я сделал наследником UIView), добавить ему полупрозрачный фон (так он смотрится красивее, чем если бы был непрозрачным), скруглить углы, поместить на него текстовую метку и отобразить его на экране.

Создаём контейнер:

CGRect tmpRect;
tmpRect.size.width = width;
tmpRect.size.height = MAX(sz.height + 20.0f, 38.0f);
tmpRect.origin.x = floor((screenWidth - width) / 2.0f);
tmpRect.origin.y = floor(screenHeight - tmpRect.size.height - 15.0f);

WToast *toast = [[WToast alloc] initWithFrame:tmpRect];
toast.backgroundColor = RGBA(0, 0, 0, 0.8f);

Обратите внимание на указание координат x и y для метки. Все координаты в iOS представлены типом float, который может принимать дробные значения. Если какому-либо элементу интерфейса задать дробные координаты, он отобразится «замыленным» (кстати, некоторые приложения в App Store грешат этим; даже в приложении от Apple для iTunes Connect была такая проблема). Во избежание этого эффекта нужно округлять координаты до целого значения. Функция floor округлит значение до нижней целой границы — то есть просто отбросит дробную часть.

RGBA — это макрос, который я написал для преобразования параметров RGB и alpha в UIColor. Он делает код компактнее и позволяет работать с RGB в привычном диапазоне 0..255 (а не 0..1, как это сделано в UIColor). Сравните размеры строки с оригинальным вызовом UIColor:

UIColor *blackTransparentColor = RGBA(0, 0, 0, 0.8f);
UIColor *blackTransparentColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.8f];

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

Мы получили наследника UIView чёрного цвета и с прозрачностью 0.8. Теперь нужно скруглить ему углы (иначе он будет выглядеть очень топорно). Для скругления можно воспользоваться инструментами, доступными в фреймворке QuartzCore. Подключаем заголовочный файл QuartzCore/QuartzCore.h и фреймворк QuartzCore и делаем следующее:

CALayer *layer = toast.layer;
layer.masksToBounds = YES;
layer.cornerRadius = 5.0f;

Параметр cornerRadius объекта CALayer задаёт радиус скругления. Попробуйте поиграться с его значением и увидите, как будет изменяться рамка нашего уведомления.

Контейнер сообщения готов, текстовую метку мы создали в самом начале — собираем это всё воедино:

textLabel.text = text;
tmpRect.origin.x = floor((toast.frame.size.width - sz.width) / 2.0f);
tmpRect.origin.y = floor((toast.frame.size.height - sz.height) / 2.0f);
tmpRect.size = sz;
textLabel.frame = tmpRect;
[toast addSubview:textLabel];
[textLabel release];
toast.alpha = 0.0f;

После выполнения этого кода наш новорожденный объект toast будет полностью прозрачным (toast.alpha = 0.0f). Это сделано для дальнейшей анимации появления.

Для запуска анимации можно воспользоваться простейшим способом, предусмотренным разработчиками iOS — блоком [UIView beginAnimations:context:] .. [UIView commitAnimations]. Все действия с объектами интерфейса, помещённые в этот блок, будут анимироваться (точнее, не совсем все; ниже я приведу пример, где анимация работать не будет):

[UIView beginAnimations:@"show" context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.2f];
[UIView setAnimationDidStopSelector:@selector(__animationDidStop:__finished:__context:)];
self.alpha = 1.0f;
[UIView commitAnimations];

Здесь мы задаём делегата, которому будет сообщено об окончании процесса анимации, продолжительность анимации и действия, которые нужно анимировать. В нашем случае это перевод объекта toast из полностью прозрачного состояния в полностью непрозрачное (self.alpha = 1.0f).

Вот что мы увидим на экране в результате выполнения нашей программы:

В методе -__animationDidStop:__finished:__context:, который вызовется по окончании анимации, включается секундный таймер, запускающий скрытие нашего сообщения:

[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(__hide) userInfo:nil repeats:NO];

Скрытие сообщения также будет анимированным:

[UIView beginAnimations:@"hide" context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.8f];
[UIView setAnimationDidStopSelector:@selector(__animationDidStop:__finished:__context:)];
self.alpha = 0.0f;
[UIView commitAnimations];

После этого объект можно удалить с экрана, вызвав метод removeFromSuperview.

Если поместить вызов removeFromSuperview в блок анимации, то исчезновение не будет анимироваться, объект исчезнет сразу после вызова этого метода. Поэтому сначала делаем «тостер» полностью прозрачным (self.alpha = 0.0f), а затем, в селекторе окончания анимации, убираем объект с экрана.

Весь цикл работы компонента будет выглядеть так:

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


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

Исходные коды компонента WToast и тестовый проект можно загрузить с github. Этот компонент можно свободно использовать в любом вашем проекте без указания авторства. Он распространяется на условиях Public Domain.

70
Логотип iPhones.ru
iPhones.ru
Для отображения всплывающих сообщений в iOS есть только один компонент — UIAlertView. Им очень удобно пользоваться, ведь создать и отобразить его можно буквально двумя-тремя строчками кода. Но у него есть один изъян: он блокирует интерфейс до того момента, пока пользователь не нажмёт кнопку, чтобы принудительно скрыть его. А иногда программисту всего лишь нужно показать какое-либо...

70 комментариев

Котик
Котик
Котик
Котик
Котик
Котик
Котик
Котик
Котик
Котик
Котик
Котик
Котик из TikTok
Котик из TikTok
Котик из TikTok
Котик из TikTok
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Момент из фильма
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Мем стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Офис стикер
Видео мем
Видео мем
Видео мем
Видео мем
Видео мем
Видео мем

Какие правила в комментариях
  1. iFanatik avatar
    iFanatik 8 апреля 2011
    0

    Спасибо за реально интересную статью. Давно таких не было.

    i.band avatar
    i.band8 апреля 2011
    0

    А вот интересно, разве всплывающие уведомления которые при изменении звука или при блокировке ориентации появляются, например, использовать нельзя для подобной цели?

    Войди на сайт, чтобы ответить
    Ответить
  2. Vizakenjack avatar
    Vizakenjack 8 апреля 2011
    0

    Отличная статья. Стоит на хабре запостить, хотя бы в песочницу

    iL0bster avatar
    iL0bster8 апреля 2011
    0

    @Vizakenjack, на хабр уже не получится: там копипаст даже своего контента запрещён. А вот как топик-ссылку… Кстати, статья великолепна! А то уже устал читать про птиц злобных. Побольше бы таких статей!

    Войди на сайт, чтобы ответить
    Ответить

Нашли орфографическую ошибку в новости?

Выделите ее мышью и нажмите Ctrl+Enter.