UISegmentedControl below UINavigationbar in iOS 7 UISegmentedControl below UINavigationbar in iOS 7 ios ios

UISegmentedControl below UINavigationbar in iOS 7


It's a simple effect to accomplish.

First, place a segment in a toolbar. Place this toolbar right below the navigation bar. Set the delegate of the toolbar to your view controller, and return UIBarPositionTopAttached in positionForBar:. You can see in the store app, if you perform an interactive pop gesture, that the segment bar does not move the same as the navigation bar. That's because they are not the same bar.

enter image description here

Now to remove the hairline. The "hairline" is an UIImageView that is a subview of the navigation bar. You can find it and set it as hidden. This is what Apple does in their native calendar app, for example, as well as the store app. Remember to show it when the current view disappears. If you play a little with the Apple apps, you will see that the hairline is set to hidden on viewWillAppear: and set to shown in viewDidDisappear:.

To achieve the style of the search bar, just set the bar's searchBarStyle to UISearchBarStyleMinimal.


Now to remove the hairline. The "hairline" is an UIImageView that is a subview of the navigation bar. You can find it and set it as hidden. This is what Apple does in their native calendar app, for example, as well as the store app. Remember to show it when the current view disappears. If you play a little with the Apple apps, you will see that the hairline is set to hidden on viewWillAppear: and set to shown in viewDidDisappear:.

Another approach would be to look for the hairline and move it below the added toolbar. Here is what I came up with.

@interface ViewController ()@property (weak, nonatomic) IBOutlet UIToolbar *segmentbar;@property (weak, nonatomic) UIImageView *navHairline;@end@implementation ViewController#pragma mark - View Lifecycle- (void)viewDidLoad{    [super viewDidLoad];    // find the hairline below the navigationBar    for (UIView *aView in self.navigationController.navigationBar.subviews) {        for (UIView *bView in aView.subviews) {            if ([bView isKindOfClass:[UIImageView class]] &&                bView.bounds.size.width == self.navigationController.navigationBar.frame.size.width &&                bView.bounds.size.height < 2) {                self.navHairline = (UIImageView *)bView;            }        }    }}- (void)viewWillAppear:(BOOL)animated{    [super viewWillAppear:animated];    [self _moveHairline:YES];}- (void)viewWillDisappear:(BOOL)animated{    [super viewWillDisappear:animated];    [self _moveHairline:NO];}- (void)_moveHairline:(BOOL)appearing{    // move the hairline below the segmentbar    CGRect hairlineFrame = self.navHairline.frame;    if (appearing) {        hairlineFrame.origin.y += self.segmentbar.bounds.size.height;    } else {        hairlineFrame.origin.y -= self.segmentbar.bounds.size.height;    }    self.navHairline.frame = hairlineFrame;}@end

I also found the Apple NavBar Code Sample (Customizing UINavigationBar) very helpful to resolve this issue.

Also be sure to handle the top border of the UIToolbar, it might show up and you could confuse it with the hairline of the NavBar. I also wanted the UIToolbar to look exactly like the NavBar, you probably want to adjust the Toolbars barTintColor then.


Here's a Protocol Oriented Swift approach to this particular problem, taking basis on the accepted answer:

HideableHairlineViewController.swift

protocol HideableHairlineViewController {  func hideHairline()  func showHairline()}extension HideableHairlineViewController where Self: UIViewController {  func hideHairline() {    findHairline()?.hidden = true  }  func showHairline() {    findHairline()?.hidden = false  }  private func findHairline() -> UIImageView? {    return navigationController?.navigationBar.subviews      .flatMap { $0.subviews }      .flatMap { $0 as? UIImageView }      .filter { $0.bounds.size.width == self.navigationController?.navigationBar.bounds.size.width }      .filter { $0.bounds.size.height <= 2 }      .first  }}

SampleViewController.swift

import UIKitclass SampleViewController: UIViewController, HideableHairlineViewController {  @IBOutlet private weak var toolbar: UIToolbar!  @IBOutlet private weak var segmentedControl: UISegmentedControl!  override func viewWillAppear(animated: Bool) {    super.viewWillAppear(animated)    hideHairline()  }  override func viewDidDisappear(animated: Bool) {    super.viewDidDisappear(animated)    showHairline()  }}// MARK: UIToolbarDelegateextension SampleViewController: UIToolbarDelegate {  func positionForBar(bar: UIBarPositioning) -> UIBarPosition {    return .TopAttached  }}