item bar swift uinavigationcontroller uinavigationbar uinavigationitem

item - navigationbar swift



Añadir subtítulo bajo el título en el controlador de la barra de navegación en Xcode (8)

Así que quiero agregar un "subtítulo" debajo del título en la barra de navegación en el controlador de navegación.

Principalmente todo lo que miro hasta ahora quiere que use CGRect. No sé mucho de qué se trata y suena como si quisiera que creara una vista completamente nueva, que no es lo que quiero hacer.

Mi pregunta es, ¿existe un método de puntos para agregar una vista de subtítulos fácilmente?

Lo más cercano que encontré fue publicado en el desbordamiento de pila y aquí está el enlace:

Crear un subtítulo en la barra de navegación

Aparentemente, el año pasado funcionó, pero ahora estoy recibiendo errores y, en mi opinión, está cargado ...

Intenté esto:

self.navigationController? .navigationItem.prompt = "Subtitle Here"

Es lo único que no muestra ningún error pero aún no funciona. Literalmente no hace nada. Al menos nada visible en tiempo de ejecución.

En una nota al margen, se prefiere swift. ¡Gracias!


¡Muchas gracias por tu respuesta! @RajanMaheshwari

Su codificación funcionó a la perfección, excepto la declaración if que hizo con el widthDiff ..

Lo ajusté un poco y todo funcionó a la perfección.

if widthDiff < 0 { let newX = widthDiff / 2 subtitleLabel.frame.origin.x = abs(newX) } else { let newX = widthDiff / 2 titleLabel.frame.origin.x = newX }

¡Gracias de nuevo por su respuesta!


Aquí está mi versión usando una vista de pila en una extensión.

extension UINavigationItem { func setTitle(title:String, subtitle:String) { let one = UILabel() one.text = title one.font = UIFont.systemFont(ofSize: 17) one.sizeToFit() let two = UILabel() two.text = subtitle two.font = UIFont.systemFont(ofSize: 12) two.textAlignment = .center two.sizeToFit() let stackView = UIStackView(arrangedSubviews: [one, two]) stackView.distribution = .equalCentering stackView.axis = .vertical let width = max(one.frame.size.width, two.frame.size.width) stackView.frame = CGRect(x: 0, y: 0, width: width, height: 35) one.sizeToFit() two.sizeToFit() self.titleView = stackView } }


Aunque hay una solución pero tiene algunos problemas conocidos.

La solución es escribir una función como esta.

func setTitle(title:String, subtitle:String) -> UIView { let titleLabel = UILabel(frame: CGRectMake(0, -2, 0, 0)) titleLabel.backgroundColor = UIColor.clearColor() titleLabel.textColor = UIColor.grayColor() titleLabel.font = UIFont.boldSystemFontOfSize(17) titleLabel.text = title titleLabel.sizeToFit() let subtitleLabel = UILabel(frame: CGRectMake(0, 18, 0, 0)) subtitleLabel.backgroundColor = UIColor.clearColor() subtitleLabel.textColor = UIColor.blackColor() subtitleLabel.font = UIFont.systemFontOfSize(12) subtitleLabel.text = subtitle subtitleLabel.sizeToFit() let titleView = UIView(frame: CGRectMake(0, 0, max(titleLabel.frame.size.width, subtitleLabel.frame.size.width), 30)) titleView.addSubview(titleLabel) titleView.addSubview(subtitleLabel) let widthDiff = subtitleLabel.frame.size.width - titleLabel.frame.size.width if widthDiff < 0 { let newX = widthDiff / 2 subtitleLabel.frame.origin.x = abs(newX) } else { let newX = widthDiff / 2 titleLabel.frame.origin.x = newX } return titleView }

Usando esta función para la vista de título de navegación personalizada en viewDidLoad

self.navigationItem.titleView = setTitle("Title", subtitle: "SubTitle")

El único problema conocido es que si el subtítulo llega a ser muy grande de lo que ocurre la mala colocación.

Resultado final

Fuente: https://gist.github.com/nazywamsiepawel/0166e8a71d74e96c7898


En caso de que alguien busque el código Objective-C de la solución mencionada.

// Fix incorrect width bug if (subtitleLabel.frame.size.width > titleLabel.frame.size.width) { var titleFrame = titleLabel.frame titleFrame.size.width = subtitleLabel.frame.size.width titleLabel.frame = titleFrame titleLabel.textAlignment = .center }


Gracias por la respuesta @RajanMaheshwari

Si alguien tiene el problema de que el título se desalinea cuando el texto del subtítulo es más largo que el texto del título, agregué el siguiente código a la respuesta del Rajan justo debajo de la instancia de la etiqueta del subtítulo:

UILable *title = [[UILabel alloc]init]; UILabel *subtitle = [[UILabel alloc]init]; [title setFont:[UIFont systemFontOfSize:12]]; [title setTextColor:[UIColor whiteColor]]; [title setFont:[UIFont systemFontOfSize:17]]; [title sizeToFit]; title.text = @"Title"; [subtitle setTextColor:[UIColor whiteColor]]; [subtitle setFont:[UIFont systemFontOfSize:12]]; [subtitle setTextAlignment:NSTextAlignmentCenter]; [subtitle sizeToFit]; subtitle.text = @"Subtitle Title"; UIStackView *stackVw = [[UIStackView alloc]initWithArrangedSubviews:@[title,subtitle]]; stackVw.distribution = UIStackViewDistributionEqualCentering; stackVw.axis = UILayoutConstraintAxisVertical; stackVw.alignment =UIStackViewAlignmentCenter; [stackVw setFrame:CGRectMake(0, 0, MAX(title.frame.size.width, subtitle.frame.size.width), 35)]; self.navigationItem.titleView = stackVw;

Espero que esto ayude a alguien que encontró el mismo problema que yo


Otra solución, utilizando solo una etiqueta y NSAttributedString para diferenciar entre título y subtítulo (con diferentes tamaños de fuente, pesos, colores, etc.) en su lugar. Elimina el problema de diferente alineación de la etiqueta.

extension UIViewController { func setTitle(_ title: String, subtitle: String) { let rect = CGRect(x: 0, y: 0, width: 400, height: 50) let titleSize: CGFloat = 20 // adjust as needed let subtitleSize: CGFloat = 15 let label = UILabel(frame: rect) label.backgroundColor = .clear label.numberOfLines = 2 label.textAlignment = .center label.textColor = .black let text = NSMutableAttributedString() text.append(NSAttributedString(string: title, attributes: [.font : UIFont.boldSystemFont(ofSize: titleSize)])) text.append(NSAttributedString(string: "/n/(subtitle)", attributes: [.font : UIFont.systemFont(ofSize: subtitleSize)])) label.attributedText = text self.navigationItem.titleView = label } }

TitleView personalizado basado en parte en https://.com/a/34298491/3918865


Realmente me gustó la respuesta de @ user2325031, pero descubrí que no era necesario cambiar el tamaño de las etiquetas para ajustarlas y establecer el marco. También establecí la alineación de stackView en .center según la sugerencia de @GerardoMR.

extension UINavigationItem { func setTitle(_ title: String, subtitle: String) { let titleLabel = UILabel() titleLabel.text = title titleLabel.font = .systemFont(ofSize: 17.0) titleLabel.textColor = .black let subtitleLabel = UILabel() subtitleLabel.text = subtitle subtitleLabel.font = .systemFont(ofSize: 12.0) subtitleLabel.textColor = .gray let stackView = UIStackView(arrangedSubviews: [titleLabel, subtitleLabel]) stackView.distribution = .equalCentering stackView.alignment = .center stackView.axis = .vertical self.titleView = stackView } }


Swift 4:

import UIKit class NavigationTitleView: UIView { private var contentStackView = UIStackView() private var titleLabel = UILabel() private var subTitleLabel = UILabel() override init(frame: CGRect) { super.init(frame: frame) viewConfig() addViewsConfig() layoutViewsConfig() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func set(title: String, subTitle: String){ self.titleLabel.text = title self.subTitleLabel.text = subTitle } private func viewConfig() { contentStackView.axis = .vertical contentStackView.alignment = .center contentStackView.distribution = .fill contentStackView.spacing = 5 self.backgroundColor = .clear self.titleLabel.textColor = .white self.self.subTitleLabel.textColor = .white } private func addViewsConfig() { contentStackView.addArrangedSubview(subTitleLabel) contentStackView.addArrangedSubview(titleLabel) self.addSubview(contentStackView) } private func layoutViewsConfig(){ contentStackView.translatesAutoresizingMaskIntoConstraints = false contentStackView.centerXAnchor.constraint(equalTo: self.centerXAnchor, constant: 0.0).isActive = true contentStackView.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 0.0).isActive = true } }

Utilizar:

import UIKit class ViewController: UIViewController { private var navigationTitleView = NavigationTitleView() override func viewDidLoad() { super.viewDidLoad() self.navigationItem.titleView = navigationTitleView navigationTitleView.set(title: "title", subTitle: "subTitle") } }