- PVSM.RU - https://www.pvsm.ru -
Добрый день!
В этой статье я хочу описать способ, при помощи которого мы сделали такой красивый кастомный progress bar — на иллюстрации — в одном из последних проектов.
Задача была поставлена следующим образом:
Заинтересовавшихся в реализации прошу под кат.
Первым делом создаем синглтон BSBeautifulProgressBarManager и прописываем в BSBeautifulProgressBarManager.h:
#import <Foundation/Foundation.h>
#define kShouldShowBeautifulProgressBar @"kShouldShowBeautifulProgressBar"
#define kShouldHideBeautifulProgressBar @"kShouldHideBeautifulProgressBar"
#define beautifulProgressBarManager [BSBeautifulProgressBarManager sharedManager]
@interface BSBeautifulProgressBarManager : NSObject
+ (BSBeautifulProgressBarManager *)sharedManager;
@end
На работе мы часто используем трюк с define, чтобы избавиться от постоянного обращения к синглтонам по названию класса. Здесь, вместо [BSBeautifulProgressBarManager sharedManager], мы можем писать просто BSBeautifulProgressBarManager. Заголовчный файл мы трогать больше не будем.
Дефайны нотификаций мы обычно выносим в какой-нибудь Config.h — тогда не нужно импортировать хедер менеджера для отправки нотификаций. Однако в данном примере мы добавим трюк с избавлением от магических констант прямо в хедер синглтона.
Обратимся к реализации синглтона в файле BSBeautifulProgressBarManager.m:
+ (BSBeautifulProgressBarManager *)sharedManager
{
static BSBeautifulProgressBarManager *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [self new];
[[NSNotificationCenter defaultCenter] addObserver:sharedManager selector:@selector(showProgressBar) name:kShouldShowBeautifulProgressBar object:nil];
[[NSNotificationCenter defaultCenter] addObserver:sharedManager selector:@selector(hideProgressBar) name:kShouldHideBeautifulProgressBar object:nil];
});
return sharedManager;
}
Ничего особенного пока что не произошло — обычная реализация thread-safe синглтона. Единственное примечательное в этом методе — это подписка на нотификации показа/скрытия progress bar'a у NSNotificationCenter.
Перейдем к реализации методов showProgressBar и hideProgressBar:
- (void)showProgressBar
{
if (isShown) return;
isShown = YES;
}
- (void)hideProgressBar
{
if (!isShown) return;
isShown = NO;
}
Пока что они ничего не делают. Однако два условия работы элемента мы уже выполнили: progress bar будет только один, и вызываться он будет через NSNotificationCenter. Соответственно, добавим в имплементацию приватную переменную:
@implementation BSBeautifulProgressBarManager
{
BOOL isShown;
}
Идея наша будет такой:
Начнем реализацию! Первым делом сменим метод showProgressBar:
- (void)showProgressBar
{
if (isShown) return;
isShown = YES;
[self addGreyView];
[self addWhiteView];
[self addGreyZip];
[self addOrangeZip];
}
Все идет по плану — мы инкапсулировали функционал добавления элементов в отдельные методы. Пройдемся по этим методам, комментарии дам чуть ниже:
@implementation BSBeautifulProgressBarManager
{
BOOL isShown;
// 1
UIView *mainView;
UIView *whiteView;
}
<...>
- (void)addGreyView
{
// 2
UIWindow *window = [[[UIApplication sharedApplication] windows] lastObject];
mainView = [[UIView alloc] initWithFrame:window.bounds];
mainView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.5];
mainView.alpha = 0.0;
[window addSubview:mainView];
// 3
[UIView animateWithDuration:0.3 animations:^{
mainView.alpha = 1.0;
}];
}
- (void)addWhiteView
{
// 4
whiteView = [[UIView alloc] initWithFrame:CGRectMake(0, -64, 320, 64)];
whiteView.backgroundColor = [UIColor whiteColor];
[mainView addSubview:whiteView];
// 5
[UIView animateWithDuration:0.3 animations:^{
CGRect frame = whiteView.frame;
frame.origin.y = 0;
whiteView.frame = frame;
}];
}
- (void)addGreyZip
{
// 6
CGRect frame = CGRectMake(0, 39, 320, 14.5);
UIImageView *greyImageView = [[UIImageView alloc] initWithFrame:frame];
greyImageView.image = [UIImage imageNamed:@"grey"];
[whiteView addSubview:greyImageView];
}
- (void)addOrangeZip
{
// 7
CGRect frame = CGRectMake(0, 0, 320, 14.5);
CGRect frameSmaller = CGRectMake(1, 39, 0, 14.5);
// 8
UIView *container = [[UIView alloc] initWithFrame:frameSmaller];
container.clipsToBounds = YES;
// 9
UIImageView *redImageView = [[UIImageView alloc] initWithFrame:frame];
redImageView.image = [UIImage imageNamed:@"red"];
[container addSubview:redImageView];
// 10
[whiteView addSubview:container];
// 11
[UIView animateWithDuration:15. animations:^{
CGRect frame = container.frame;
frame.size.width = 320;
container.frame = frame;
}];
}
Пойдем по-порядку:
Замечательно! Теперь мы можем показать прогресс бар, когда нужно. Перейдем к реализации методов прятания прогресс-бара:
- (void)hideProgressBar
{
if (!isShown) return;
isShown = NO;
[self hideGreyView];
[self hideWhiteView];
[self finish];
}
Идея проста: прячем основную вьюху (черную-полупрозрачную или, просто, серую), в это время убираем вверх белую вьюху со всеми ее внутренностями, да еще и оранжевую молнию доводим мгновенно до конца — ведь, если она не расширена до конца, значит нужно довести, чтобы показать юзеру, мол, действие завершено.
Приступим к реализации, комментарии ниже:
- (void)hideGreyView
{
// 1
[UIView animateWithDuration:0.3 animations:^{
mainView.alpha = 0.0;
} completion:^(BOOL finished){
[mainView removeFromSuperview];
}];
}
- (void)hideWhiteView
{
// 2
[UIView animateWithDuration:0.3 animations:^{
CGRect frame = whiteView.frame;
frame.origin.y = -64;
whiteView.frame = frame;
}];
}
- (void)finish
{
// 3
CGRect frame = CGRectMake(0, 39, 320, 14.5);
UIImageView *greyImageView = [[UIImageView alloc] initWithFrame:frame];
greyImageView.backgroundColor = [UIColor whiteColor];
greyImageView.image = [UIImage imageNamed:@"grey"];
[whiteView addSubview:greyImageView];
// 4
frame = CGRectMake(1, 39, 320, 14.5);
UIImageView *redImageView = [[UIImageView alloc] initWithFrame:frame];
redImageView.image = [UIImage imageNamed:@"red"];
[whiteView addSubview:redImageView];
}
Все просто:
Кстати, вот и нужные картинки:
Вот и все! Вы познали кусочек реальной, работающей социальной сети. Фактически, окунулись в код из продакшна. Мы можем вызывать кастомный, красивый progress bar при помощи посылки нужных нотификаций.
Спасибо, что дочитали до конца! Я с радостью отвечу на любые ваши вопросы. Если вы нашли какие-нибудь опечатки или неточности — смело пишите в мой Хабрацентр!
Обязательно напишите, что же вы хотите увидеть в следующей статье.
Автор: backmeupplz
Источник [1]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/ios/65964
Ссылки в тексте:
[1] Источник: http://habrahabr.ru/post/231117/
Нажмите здесь для печати.