我終於找到了解決方案。
我不得不用我的自定義子類重寫UINavigation bar以改變高度。通過使用外觀代理,標題和導航項目可以正確地重新定位。不幸的是,代理不能用於向後移動後退按鈕的箭頭(在iOS 7上),所以我們必須重寫layoutSubview來處理該事件。
#define kAppNavBarHeight 66.0
@implementation TATallNavigationBar
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self setupAppearance];
}
return self;
}
- (id)init
{
self = [super init];
if (self) {
[self setupAppearance];
}
return self;
}
- (void)setupAppearance {
static BOOL appearanceInitialised = NO;
if (!appearanceInitialised) {
// Update the appearance of this bar to shift the icons back up to their normal position
CGFloat offset = 44 - kAppNavBarHeight;
[[TATallNavigationBar appearance] setTitleVerticalPositionAdjustment:offset forBarMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearanceWhenContainedIn:[RRSNavigationBar class], nil] setBackgroundVerticalPositionAdjustment:offset forBarMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearanceWhenContainedIn:[RRSNavigationBar class], nil] setBackButtonBackgroundVerticalPositionAdjustment:offset forBarMetrics:UIBarMetricsDefault];
[[UIBarButtonItem appearanceWhenContainedIn:[RRSNavigationBar class], nil] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, offset) forBarMetrics:UIBarMetricsDefault];
appearanceInitialised = YES;
}
}
- (CGSize)sizeThatFits:(CGSize)size {
return CGSizeMake(self.superview.frame.size.width, kNavBarheight);
}
- (void)layoutSubviews {
static CGFloat yPosForArrow = -1;
[super layoutSubviews];
// There's no official way to reposition the back button's arrow under iOS 7. It doesn't shift with the title.
// We have to reposition it here instead.
for (UIView *view in self.subviews) {
// The arrow is a class of type _UINavigationBarBackIndicatorView. We're not calling any private methods, so I think
// this is fine for the AppStore...
if ([NSStringFromClass([view class]) isEqualToString:@"_UINavigationBarBackIndicatorView"]) {
CGRect frame = view.frame;
if (yPosForArrow < 0) {
// On the first layout we work out what the actual position should be by applying our offset to the default position.
yPosForArrow = frame.origin.y + (44 - kAppNavBarHeight);
}
// Update the frame.
frame.origin.y = yPosForArrow;
view.frame = frame;
}
}
}
@end
注意,很容易在XCode中可以指定子類:點擊UINavigationController的,您可以訪問到UINavigationBar的在左欄中。點擊它並在檢查器中更改它的子類。
我也創建了這個要點:
https://gist.github.com/timothyarmes/7080170
如何確定你是對_UINavigationBarBackIndicatorView使用是可以接受的?這是一個無證的財產,如果蘋果改變它,你的應用程序可能會被打破。 – Tim
我只是在測試類的類型,所以從接受的角度來看應該沒問題。它可能會在未來的操作系統更新中發生變化,但我不認爲這會很快發生,所以我個人確定。如果你願意的話,你總是可以嘗試找到另一種方法來檢查特定的視圖(例如,我的代碼的第一個版本,我看它的大小和位置)。 – tarmes
我遇到了另一個使用我自己版本的解決方案的問題,後來出現了問題,因爲我推送了更多的視圖控制器,我不需要這麼高 - 關於如何將它變成更優雅的解決方案的任何想法? – Tim