В ходе разработки одного приложения столкнулся с проблемой: стандартный iOS-овский tabbar очень плохо поддается кастомизации. Невозможно легким движением руки поставить цветные иконки для табов, ни поменять бэкграунд как самого таб-бара, так и отдельных табов в различных состояниях (активен, не активен).
Тем не менее, задача стояла четко: внедрить имеющийся дизайн, который категорически не состыковывался с накладываемыми ограничениями.
В целом, проблему можно разделить на 3 этапа:
- Цветные иконки.
- Разный бэкграунд в различных состояниях табов.
- Кастомный бэкграунд самого таб-бара
С иконками проблема состоит в следующем: свойство image класса UITabbar на самом деле не меняет иконку, как было бы очевидней, а всего лишь использует наше изображение в качестве маски для иконки (подробней можно почитать здесь). Такая ситуация меня естественно не устраивала. Эта проблема решилась быстрее и легче всего.
Для решения оставшихся двух пришлось включать голову (поскольку UITabBarItem не является наследником UIView и поэтому не имеет почти никаких полезных свойств) — попытка откопать что-то в интернете не возымела успеха — большинство советов сводилось к «напиши свой собственный таб-бар с блэкджеком и шлюхами».
В итоге был написан простенький класс:
@interface KidsReviewTabBarController : UITabBarController <UITabBarControllerDelegate>
@end
@implementation KidsReviewTabBarController
{
UIImageView *_selection;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.delegate = self;
[self initTabBar];
}
- (void)initTabBar
{
//Загружаем изображения для иконок
UIImage *firstImage = [UIImage imageNamed:@"first_icon.png"];
UIImage *secondImage = [UIImage imageNamed:@"second_icon.png"];
UIImage *thirdImage = [UIImage imageNamed:@"third_icon.png"];
UIImage *firstImageSelected = [UIImage imageNamed:@"first_icon_selected.png"];
UIImage *secondImageSelected = [UIImage imageNamed:@"second_icon_selected.png"];
UIImage *thirdImageSelected = [UIImage imageNamed:@"third_icon_selected.png"];
//Получаем элементы таб-бара
UITabBarItem *firstItem = [self.tabBar.items objectAtIndex:0];
UITabBarItem *secondItem = [self.tabBar.items objectAtIndex:1];
UITabBarItem *thirdItem = [self.tabBar.items objectAtIndex:2];
//Устанавливаем иконки для каждого из табов
[firstItem setFinishedSelectedImage:firstImageSelected withFinishedUnselectedImage:firstImage];
[secondItem setFinishedSelectedImage:secondImageSelected withFinishedUnselectedImage:secondImage];
[thirdItem setFinishedSelectedImage:thirdImageSelected withFinishedUnselectedImage:thirdImage];
//Кастомизируем бэкграунд таб-бара
UIImage *backgroundImage = [UIImage imageNamed:@"tabbar_background.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:backgroundImage];
CGRect frame = imageView.frame;
frame.size.width = self.tabBar.frame.size.width;
imageView.frame = frame;
[[self tabBar] insertSubview:imageView atIndex:1];
//Инициалиизируем бэкграунд иконки и устанавливаем его для первого элемента таб-бара
//Это необходимо поскольку метод tabBarController:didSelectViewController: не вызывается при загрузке
//приложения (когда первый элемент должен быть активным)
_selection = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"tabbar_selection.png"]];
[[self buttonByIndex:0] insertSubview:_selection atIndex:0];
}
//Реализуем метод протокола UITabBarControllerDelegate (вызывается после выбора таба)
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
//получаем UIView, содержащий необходимый нам элемент таб-бара, удаляем бэкграунд с предыдущего таба и
//устанавливаем на текущий
UIView *selectedButton = [self buttonByIndex:tabBarController.selectedIndex];
[_selection removeFromSuperview];
[selectedButton insertSubview:_selection atIndex:1];
}
- (UIView *) buttonByIndex:(int)index
{
NSMutableArray *buttons = [[NSMutableArray alloc] init];
for (UIControl* btn in self.tabBar.subviews)
{
if ([btn isKindOfClass:[UIControl class]])
{
[buttons addObject:btn];
}
}
return [buttons objectAtIndex:(NSUInteger) index];
}
Для решения задачи не обязательно создавать наследника UITabBarController как это сделал я, достаточно реализовать в каком-либо классе протокол UITabBarControllerDelegate и там отслеживать состояние таб-бара, ну и где-нибудь инициализировать иконки и бэкграунд.
Мне был более удобен вариант с наследованием от UITabBarController, поскольку шрифты и надписи менять не было необходимости и их поведение по дефолту меня полностью устраивало.
P.S. Возможно, пост получился несколько сумбурным. Если что-то непонятно — пишите.
Автор: afterwhy