ios uinavigationbar uisegmentedcontrol

UISegmentedControl debajo de UINavigationbar en iOS 7



(10)

Ahora para quitar la línea del cabello. La "línea del cabello" es un UIImageView que es una subvista de la barra de navegación. Puede encontrarlo y configurarlo como oculto. Esto es lo que hace Apple en su aplicación de calendario nativo, por ejemplo, así como en la aplicación de la tienda. Recuerde mostrarlo cuando desaparece la vista actual. Si juegas un poco con las aplicaciones de Apple, verás que la línea de implantación del cabello está oculta en viewWillAppear: y configurada como se muestra en viewDidDisappear :.

Otro enfoque sería buscar la línea del cabello y moverla debajo de la barra de herramientas agregada. Esto es lo que se me ocurrió.

@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

También encontré la muestra de código Apple NavBar (Personalización de UINavigationBar) muy útil para resolver este problema.

También asegúrese de manejar el borde superior de la barra de herramientas de UIT , podría aparecer y podría confundirlo con la rayita del NavBar. También quería que el UIToolbar se viera exactamente como el NavBar, entonces probablemente quieras ajustar las Barras de herramientas barTintColor .

¿Cómo hago un UISegmentedControl como parte de un UINavigationBar debajo de él? ¿Está conectado a UINavigationBar o es una vista completa separada que se acaba de agregar como subvista al controlador de vista de UINavigationController ? Parece que es parte de UINavigationBar ya que hay una sombra debajo de la barra.


UISegmentedControl debajo de UINavigationbar en swift 3/4

Detalles

Xcode 9.2, veloz 4

Muestra completa

ViewController.swift

import UIKit class ViewController: UIViewController { @IBOutlet weak var tableView: UITableView! @IBOutlet weak var navigationBarWithSegmentedControl: UINavigationBar! fileprivate let barBackgroundColor = UIColor(red: 248/255, green: 248/255, blue: 248/255, alpha: 1.0) override func viewDidLoad() { super.viewDidLoad() navigationBarWithSegmentedControl.barTintColor = barBackgroundColor tableView.dataSource = self tableView.delegate = self } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) navigationController?.navigationBar.shadowImage = UIImage() navigationController?.navigationBar.barTintColor = barBackgroundColor } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) navigationController?.navigationBar.setBackgroundImage(nil, for: .default) navigationController?.navigationBar.shadowImage = nil } } extension ViewController: UITableViewDataSource { func numberOfSections(in tableView: UITableView) -> Int { return 1 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 100 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell cell.label.text = "/(indexPath)" return cell } } extension ViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if let cell = tableView.cellForRow(at: indexPath) { cell.isSelected = false } } }

TableViewCell.swift

import UIKit class TableViewCell: UITableViewCell { @IBOutlet weak var label: UILabel! }

Main.storyboard

<?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="5TT-dT-dEr"> <device id="retina4_7" orientation="portrait"> <adaptation id="fullscreen"/> </device> <dependencies> <deployment identifier="iOS"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/> <capability name="Constraints to layout margins" minToolsVersion="6.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> <!--Text--> <scene sceneID="tne-QT-ifu"> <objects> <viewController id="BYZ-38-t0r" customClass="ViewController" customModule="_21887252" customModuleProvider="target" sceneMemberID="viewController"> <layoutGuides> <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> </layoutGuides> <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <rect key="frame" x="0.0" y="0.0" width="375" height="603"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="HLl-W2-Moq"> <rect key="frame" x="0.0" y="44" width="375" height="559"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <prototypes> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="TableViewCell" id="FKA-c2-G0Q" customClass="TableViewCell" customModule="_21887252" customModuleProvider="target"> <rect key="frame" x="0.0" y="28" width="375" height="44"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="FKA-c2-G0Q" id="Xga-fr-00H"> <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QW3-Hg-hU9"> <rect key="frame" x="15" y="11" width="345" height="21"/> <fontDescription key="fontDescription" type="system" pointSize="17"/> <nil key="textColor"/> <nil key="highlightedColor"/> </label> </subviews> <constraints> <constraint firstAttribute="trailingMargin" secondItem="QW3-Hg-hU9" secondAttribute="trailing" id="Grx-nu-2Tu"/> <constraint firstItem="QW3-Hg-hU9" firstAttribute="centerY" secondItem="Xga-fr-00H" secondAttribute="centerY" id="MIn-R2-wYE"/> <constraint firstItem="QW3-Hg-hU9" firstAttribute="leading" secondItem="Xga-fr-00H" secondAttribute="leadingMargin" id="h6T-gt-4xk"/> </constraints> </tableViewCellContentView> <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.050000000000000003" colorSpace="custom" customColorSpace="sRGB"/> <connections> <outlet property="label" destination="QW3-Hg-hU9" id="QjK-i2-Ckd"/> <segue destination="hcx-2g-4ts" kind="show" id="IGa-oI-gtf"/> </connections> </tableViewCell> </prototypes> </tableView> <navigationBar contentMode="scaleToFill" translucent="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8jj-w6-ZtU"> <rect key="frame" x="0.0" y="0.0" width="375" height="44"/> <items> <navigationItem id="q8e-Yy-ceD"> <nil key="title"/> <segmentedControl key="titleView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="bar" selectedSegmentIndex="0" id="cHD-bv-2w7"> <rect key="frame" x="96.5" y="7" width="182" height="30"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <segments> <segment title="First"/> <segment title="Second"/> <segment title="Third"/> </segments> </segmentedControl> </navigationItem> </items> </navigationBar> </subviews> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstItem="8jj-w6-ZtU" firstAttribute="trailing" secondItem="HLl-W2-Moq" secondAttribute="trailing" id="1vT-ta-AuP"/> <constraint firstItem="8jj-w6-ZtU" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="BJE-BC-XcB"/> <constraint firstItem="8jj-w6-ZtU" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" id="Boi-dN-awt"/> <constraint firstItem="HLl-W2-Moq" firstAttribute="bottom" secondItem="wfy-db-euE" secondAttribute="top" id="W1n-m1-EOH"/> <constraint firstAttribute="trailing" secondItem="8jj-w6-ZtU" secondAttribute="trailing" id="ihc-9p-71l"/> <constraint firstItem="HLl-W2-Moq" firstAttribute="top" secondItem="8jj-w6-ZtU" secondAttribute="bottom" id="pFk-pU-y7j"/> <constraint firstItem="8jj-w6-ZtU" firstAttribute="leading" secondItem="HLl-W2-Moq" secondAttribute="leading" id="yjf-7o-t2m"/> </constraints> </view> <navigationItem key="navigationItem" title="Text" id="yrt-M7-PAX"> <barButtonItem key="leftBarButtonItem" systemItem="search" id="wrz-DS-FdJ"/> <barButtonItem key="rightBarButtonItem" systemItem="add" id="LnB-Ci-YnO"/> </navigationItem> <connections> <outlet property="navigationBarWithSegmentedControl" destination="8jj-w6-ZtU" id="Ggl-xb-fmj"/> <outlet property="tableView" destination="HLl-W2-Moq" id="hEO-2U-I9k"/> </connections> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> </objects> <point key="canvasLocation" x="894" y="791"/> </scene> <!--View Controller--> <scene sceneID="Bi7-4l-uRN"> <objects> <viewController id="hcx-2g-4ts" sceneMemberID="viewController"> <layoutGuides> <viewControllerLayoutGuide type="top" id="NSV-kw-fuz"/> <viewControllerLayoutGuide type="bottom" id="aze-le-h11"/> </layoutGuides> <view key="view" contentMode="scaleToFill" id="1nd-qq-kDT"> <rect key="frame" x="0.0" y="0.0" width="375" height="603"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="k7W-CB-tpA"> <rect key="frame" x="0.0" y="0.0" width="375" height="603"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> </view> </subviews> <color key="backgroundColor" white="0.66666666666666663" alpha="0.5" colorSpace="calibratedWhite"/> <constraints> <constraint firstAttribute="trailing" secondItem="k7W-CB-tpA" secondAttribute="trailing" id="1t2-Bi-dR7"/> <constraint firstItem="k7W-CB-tpA" firstAttribute="bottom" secondItem="aze-le-h11" secondAttribute="top" id="Fnm-UL-geX"/> <constraint firstItem="k7W-CB-tpA" firstAttribute="leading" secondItem="1nd-qq-kDT" secondAttribute="leading" id="bKV-7A-hz0"/> <constraint firstItem="k7W-CB-tpA" firstAttribute="top" secondItem="NSV-kw-fuz" secondAttribute="bottom" id="cFH-7i-vAm"/> </constraints> </view> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="jPK-Z9-yvJ" userLabel="First Responder" sceneMemberID="firstResponder"/> </objects> <point key="canvasLocation" x="1566" y="791"/> </scene> <!--Navigation Controller--> <scene sceneID="1Pc-qt-rnW"> <objects> <navigationController automaticallyAdjustsScrollViewInsets="NO" id="5TT-dT-dEr" sceneMemberID="viewController"> <toolbarItems/> <navigationBar key="navigationBar" contentMode="scaleToFill" translucent="NO" id="lPt-hx-iar"> <rect key="frame" x="0.0" y="20" width="375" height="44"/> <autoresizingMask key="autoresizingMask"/> </navigationBar> <nil name="viewControllers"/> <connections> <segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="6b8-br-zSy"/> </connections> </navigationController> <placeholder placeholderIdentifier="IBFirstResponder" id="u7U-GH-NHe" userLabel="First Responder" sceneMemberID="firstResponder"/> </objects> <point key="canvasLocation" x="140" y="791.15442278860576"/> </scene> </scenes> </document>

Resultados


Yo quería hacer lo mismo ... Y obtuve esto:

1 - Subclase UINavigationBar

//------------------------- // UINavigationBarCustom.h //------------------------- #import <UIKit/UIKit.h> @interface UINavigationBarCustom : UINavigationBar @end //------------------------- // UINavigationBarCustom.m //------------------------- #import "UINavigationBarCustom.h" const CGFloat MyNavigationBarHeightIncrease = 38.f; @implementation UINavigationBarCustom - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { [self initialize]; } return self; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self initialize]; } return self; } - (void)initialize { // Set tittle position for top [self setTitleVerticalPositionAdjustment:-(MyNavigationBarHeightIncrease) forBarMetrics:UIBarMetricsDefault]; } - (CGSize)sizeThatFits:(CGSize)size { // Increase NavBar size CGSize amendedSize = [super sizeThatFits:size]; amendedSize.height += MyNavigationBarHeightIncrease; return amendedSize; } - (void)layoutSubviews { // Set buttons position for top [super layoutSubviews]; NSArray *classNamesToReposition = @[@"UINavigationButton"]; for (UIView *view in [self subviews]) { if ([classNamesToReposition containsObject:NSStringFromClass([view class])]) { CGRect frame = [view frame]; frame.origin.y -= MyNavigationBarHeightIncrease; [view setFrame:frame]; } } } - (void)didAddSubview:(UIView *)subview { // Set segmented position [super didAddSubview:subview]; if ([subview isKindOfClass:[UISegmentedControl class]]) { CGRect frame = subview.frame; frame.origin.y += MyNavigationBarHeightIncrease; subview.frame = frame; } } @end

2 - Configure su NavigationController con la subclase

3 - Agregue su UISegmentedControl en navigationBar

4 - Run and Fun -> no olvides poner el mismo color en ambos

fuente de búsqueda:

Hackear UINavigationBar

ASI pregunta


Apple tiene una aplicación de muestra específicamente para esto. Describe la configuración de una imagen de sombra transparente y una imagen de fondo de color para la barra de navegación y cómo configurar una vista debajo de la barra de navegación. También tiene ejemplos de otras personalizaciones de barras de navegación.

Ver https://developer.apple.com/library/ios/samplecode/NavBar/Introduction/Intro.html


Aquí hay un enfoque Swift orientado a los protocolos para este problema en particular, tomando como base la respuesta aceptada:

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 UIKit class 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: UIToolbarDelegate extension SampleViewController: UIToolbarDelegate { func positionForBar(bar: UIBarPositioning) -> UIBarPosition { return .TopAttached } }


Es un efecto simple de lograr.

Primero, coloca un segmento en una barra de herramientas. Coloque esta barra de herramientas justo debajo de la barra de navegación. Establezca el delegado de la barra de herramientas en su controlador de vista y devuelva UIBarPositionTopAttached en positionForBar: Puede ver en la aplicación de la tienda, si realiza un gesto pop interactivo, que la barra de segmento no se mueve igual que la barra de navegación. Eso es porque no son el mismo bar.

Ahora para quitar la línea del cabello. La "línea del cabello" es un UIImageView que es una subvista de la barra de navegación. Puede encontrarlo y configurarlo como oculto. Esto es lo que hace Apple en su aplicación de calendario nativo, por ejemplo, así como en la aplicación de la tienda. Recuerde mostrarlo cuando desaparece la vista actual. Si juegas un poco con las aplicaciones de Apple, verás que la línea de implantación del cabello está oculta en viewWillAppear: y configurada como se muestra en viewDidDisappear:

Para lograr el estilo de la barra de búsqueda, simplemente establece searchBarStyle en UISearchBarStyleMinimal .


Hay muchas maneras de hacer lo que pediste. El más fácil es, por supuesto, crearlo en el constructor de interfaz, pero supongo que esto no es lo que tenía en mente. Creé un ejemplo de la imagen que publicaste arriba. No es exactamente lo mismo, pero puede jugar con las numerosas propiedades para obtener la apariencia de lo que está buscando.

En ViewController.h

#import <UIKit/UIKit.h> @interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate> @end

En ViewController.m

#import "ViewController.h" @interface ViewController () @property (strong, nonatomic) UISegmentedControl *mySegmentControl; @property (strong, nonatomic) UISearchBar *mySearchBar; @property (strong, nonatomic) UITableView *myTableView; @property (strong, nonatomic) NSMutableArray *tableDataArray; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // create a custom UIView UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 64, 320, 84)]; myView.tintColor = [UIColor lightGrayColor]; // change tiny color or delete this line to default // create a UISegmentControl self.mySegmentControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"All", @"Not on this iPhone", nil]]; self.mySegmentControl.selectedSegmentIndex = 0; [self.mySegmentControl addTarget:self action:@selector(segmentAction:) forControlEvents:UIControlEventValueChanged]; self.mySegmentControl.frame = CGRectMake(20, 10, 280, 30); [myView addSubview:self.mySegmentControl]; // add segment control to custom view // create UISearchBar self.mySearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 40, 320, 44)]; [self.mySearchBar setDelegate:self]; self.mySearchBar.searchBarStyle = UISearchBarStyleMinimal; [myView addSubview:self.mySearchBar]; // add search bar to custom view [self.view addSubview:myView]; // add custom view to main view // create table data array self.tableDataArray = [[NSMutableArray alloc] initWithObjects: @"Line 1", @"Line 2", @"Line 3", @"Line 4", @"Line 5", @"Line 6", @"Line 7", @"Line 8", @"Line 9", @"Line 10", @"Line 11", @"Line 12", nil]; self.myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 160, 320, 320)]; [self.myTableView setDataSource:self]; [self.myTableView setDelegate:self]; [self.view addSubview:self.myTableView]; // add table to main view } -(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { [searchBar resignFirstResponder]; NSLog(@"search text = %@",searchBar.text); // code for searching... } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.tableDataArray count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; } cell.textLabel.text = [self.tableDataArray objectAtIndex:indexPath.row]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"Selected table item: %@",[self.tableDataArray objectAtIndex:indexPath.row]); // do something once user has selected a table cell... } -(void)segmentAction:(id)sender { NSLog(@"Segment control changed to: %@",[self.mySegmentControl titleForSegmentAtIndex:[self.mySegmentControl selectedSegmentIndex]]); // do something based on segment control selection... } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end


Intenté quitar la línea del cabello usando el método de @ Simon, pero no funcionó. Probablemente estoy haciendo algo mal porque soy súper novato. Sin embargo, en lugar de eliminar la línea, simplemente puede ocultarla utilizando el atributo hidden . Aquí está el código:

var hairLine: UIView = UIView() override func viewDidLoad() { super.viewDidLoad() doneButton.enabled = false for parent in self.navigationController!.navigationBar.subviews { for childView in parent.subviews { if childView is UIImageView && childView.bounds.size.width == self.navigationController!.navigationBar.frame.size.width { hairLine = childView } } } } override func viewWillAppear(animated: Bool) { hairLine.hidden = true } override func viewWillDisappear(animated: Bool) { hairLine.hidden = false }

Espero que esto ayude a alguien!



displaysSearchBarInNavigationBar es la forma de mostrar una barra de búsqueda, así como su barra de alcance en la barra de navegación.

solo tiene que ocultar la barra de búsqueda cada vez que muestre un título personalizado