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.
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")
}
}