2013-10-20 33 views
2

第二图像此页面上,从苹果的用户界面设计指南显示一个高大的导航条内分段控制:这种导航控制是如何被创建

https://developer.apple.com/library/ios/documentation/userexperience/conceptual/mobilehig/Anatomy.html#//apple_ref/doc/uid/TP40006556-CH24-SW1

这是如何完成的?在我看来,UINavigationBar总是64像素高,所以我不明白他们是如何使这个更高。

它是一个自定义元素(这在本文档中会令人惊讶),还是有一个简单的方法来实现这一点?我想知道如果它是一个UIToolbar ...他们是否与iOS 7下的UINavigationBar合并?如果是这样,我们该怎么做?

请注意,我需要在iPad应用程序中执行此操作,其中UINavigationController位于分割视图控制器中。

回答

2

我终于找到了解决方案。

我不得不用我的自定义子类重写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

+0

如何确定你是对_UINavigationBarBackIndicatorView使用是可以接受的?这是一个无证的财产,如果苹果改变它,你的应用程序可能会被打破。 – Tim

+1

我只是在测试类的类型,所以从接受的角度来看应该没问题。它可能会在未来的操作系统更新中发生变化,但我不认为这会很快发生,所以我个人确定。如果你愿意的话,你总是可以尝试找到另一种方法来检查特定的视图(例如,我的代码的第一个版本,我看它的大小和位置)。 – tarmes

+0

我遇到了另一个使用我自己版本的解决方案的问题,后来出现了问题,因为我推送了更多的视图控制器,我不需要这么高 - 关于如何将它变成更优雅的解决方案的任何想法? – Tim