Хорошо, у нас очень длинный путь.
При чтении из документа поведение по умолчанию становится понятным: если свойство hides...
контроллера представления имеет значение YES, панель вкладок скрывается до тех пор, пока контроллер представления не будет извлечен. То, что вы хотите, прямо противоречит этому, и по разным причинам я бы сначала рекомендовал не использовать этот подход.
Однако это не значит, что это невозможно реализовать.
- Установка
hides...
свойства обратно в NO
Вы не можете изменить поведение по умолчанию. Чтобы отобразить панель вкладок, все контроллеры представления в стеке должны установить для своего свойства hides...
значение NO. Таким образом, в представлении, где панель вкладок скрыта, если вы хотите снова отобразить панель при нажатии нового представления, вам необходимо снова установить свойство hides...
контроллера предыдущего представления в NO
.
Непосредственно перед тем, как нажать новый контроллер представления, установите для свойства значение NO.
// ... prepare viewControllerToPush
self.hidesBottomBarWhenPushed = NO;
[self.navigationController pushViewController:viewControllerToPush animated:YES];
[viewControllerToPush release];
Сделав это, вы снова получите панель вкладок. Однако вы узнаете, что панель вкладок вставлена слева, а новый вид - справа. Это явно нежелательно, поэтому нам нужно это исправить.
- Переопределение действия слоя для панели вкладок
Дело в том, что действие слоя по умолчанию (анимация), используемое при повторном появлении панели вкладок, - это анимация push-перехода слева. UITabBar реализует метод - (id < CAAction >)actionForLayer:(CALayer *)layer forKey:(NSString *)key
, который указывает использовать анимацию слева для случая. Нам нужно переопределить этот метод, чтобы вместо этого вернуть анимацию справа.
Чтобы показать панель вкладок назад, Cocoa изменяет свойство position
своего слоя. Поэтому наш новый метод должен возвращать анимацию справа для ключа position
, а для всех остальных ключей он должен использовать реализацию по умолчанию. Обратите внимание, что использование position
для панели вкладок не задокументировано Apple, поэтому может быть изменено без уведомления в следующих версиях. В любом случае, мы реализуем что-то, что прямо противоречит спецификации Apple, поэтому не могу много жаловаться.
Однако вы не можете просто использовать подклассы для переопределения метода. Потому что даже если у вас есть собственный подкласс UITabBar, вы не можете изменить класс UITabBarController, чтобы использовать его вместо UITabBar по умолчанию.
Итак, все становится немного сложнее. Чтобы внедрить свою собственную логику в класс UITabBar, вы должны «поменять» реализацию сообщения actionForLayer: forKey:
.
Сначала добавьте новый метод в класс UITabBar, используя категорию.
@interface UITabBar(customAction)
@end
@implementation UITabBar(customAction)
- (id < CAAction >)customActionForLayer:(CALayer *)layer forKey:(NSString *)key {
if ([key isEqualToString:@"position"]) {
CATransition *pushFromRight = [[CATransition alloc] init];
pushFromRight.duration = 0.25;
pushFromRight.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
pushFromRight.type = kCATransitionPush;
pushFromRight.subtype = kCATransitionFromRight;
return [pushFromRight autorelease];
}
return [self defaultActionForLayer:layer forKey:key];
}
@end
А в методе viewDidAppear
контроллера панели вкладок введите следующие коды.
Method original = class_getInstanceMethod([UITabBar class], @selector(actionForLayer:forKey:));
Method custom = class_getInstanceMethod([UITabBar class], @selector(customActionForLayer:forKey:));
class_replaceMethod([UITabBar class], @selector(actionForLayer:forKey:), method_getImplementation(custom), method_getTypeEncoding(custom));
class_addMethod([UITabBar class], @selector(defaultActionForLayer:forKey:), method_getImplementation(original), method_getTypeEncoding(original));
Вы хотите сделать это в viewDidAppear
, а не viewDidLoad
, потому что в противном случае панель вкладок будет сдвигаться вправо при первом появлении приложения.
Теперь, когда экземпляр UITabBar получает сообщение actionsForLayer forKey:
, вызывается пользовательский метод customActionForLayer forKey:
. Он перехватывает клавишу position
и возвращает анимацию справа. Если это для другого ключа, он вызывает исходную реализацию сообщения, которая теперь связана с сообщением defaultActionsForLayer forKey:
.
Хорошо, вот и мы. Помните, что при возврате представлений вам может потребоваться установить для свойства hides...
значение YES, поскольку вы устанавливаете его в значение NO при нажатии нового представления (и выполняете некоторые аналогичные приемы для его правильной анимации).
Я потратил некоторое время на это, но по иронии судьбы, должен сказать * Не используйте этот снова, потому что он использует недокументированную информацию классов Какао (клавиша «позиция» для анимации панели вкладок) , противоречит задокументированному поведению и противоречит руководству Apple по человеческому интерфейсу. Вы можете обнаружить, что ваше приложение не будет работать одинаково со следующими версиями SDK, что пользователи не смогут легко перенять интерфейс или даже Apple отклонит ваше приложение в магазине приложений.
Тогда зачем мне мой ответ? Ну, я думаю, пример некоторых интересных тем по разработке под iOS (и доказательство того, что я сегодня ужасно непродуктивен: P).