Je souhaite donc ajouter un "sous-titre" sous le titre dans la barre de navigation du contrôleur de navigation.
Pour l’essentiel, tout ce que j’ai levé jusqu’à présent veut que j’utilise CGRect. Je ne sais pas trop ce que c'est et cela ressemble à sa volonté de me créer une toute nouvelle vue, ce qui n'est pas ce que je veux faire.
Ma question est la suivante: existe-t-il une méthode de points pour ajouter facilement une vue de sous-titres?
La chose la plus proche que j'ai trouvée a été postée sur le débordement de la pile et voici le lien:
Créer un sous-titre dans la barre de navigation
Apparemment, l'année dernière, cela a fonctionné, mais maintenant je reçois des erreurs et c'est dans mon point de vue ...
J'ai essayé ceci:
self.navigationController? .navigationItem.Prompt = "Sous-titre ici"
C'est la seule chose qui ne montre aucune erreur mais qui ne fonctionne toujours pas. Il ne fait littéralement rien. Au moins rien de visible au moment de l'exécution.
Sur une note de côté, Swift est préféré. Merci!
Bien qu'il existe une solution, mais il a quelques problèmes connus
Solution écrit une fonction comme celle-ci
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
}
Utilisation de cette fonction pour l’affichage du titre de navigation personnalisé dans viewDidLoad
self.navigationItem.titleView = setTitle("Title", subtitle: "SubTitle")
Le seul problème connu est que si le sous-titre devient très volumineux, le mauvais placement se produit.
Source: https://Gist.github.com/nazywamsiepawel/0166e8a71d74e96c7898
Voici ma version utilisant une vue de pile sur une extension.
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
}
}
Merci beaucoup pour votre réponse! @ RajanMaheshwari
Votre codage a parfaitement fonctionné, sauf la déclaration if que vous avez faite avec widthDiff.
Je l'ai ajusté un peu et tout s'est bien passé.
if widthDiff < 0 {
let newX = widthDiff / 2
subtitleLabel.frame.Origin.x = abs(newX)
} else {
let newX = widthDiff / 2
titleLabel.frame.Origin.x = newX
}
Merci encore pour votre réponse!
L'extension Swift 4 de @ iosjillian fonctionne parfaitement, en ajoutant un peu plus pour honorer l'apparence de la barre et les préférences de police de l'utilisateur:
import UIKit
extension UINavigationItem {
func setTitle(_ title: String, subtitle: String) {
let appearance = UINavigationBar.appearance()
let textColor = appearance.titleTextAttributes?[NSAttributedString.Key.foregroundColor] as? UIColor ?? .black
let titleLabel = UILabel()
titleLabel.text = title
titleLabel.font = .preferredFont(forTextStyle: UIFont.TextStyle.headline)
titleLabel.textColor = textColor
let subtitleLabel = UILabel()
subtitleLabel.text = subtitle
subtitleLabel.font = .preferredFont(forTextStyle: UIFont.TextStyle.subheadline)
subtitleLabel.textColor = textColor.withAlphaComponent(0.75)
let stackView = UIStackView(arrangedSubviews: [titleLabel, subtitleLabel])
stackView.distribution = .equalCentering
stackView.alignment = .center
stackView.axis = .vertical
self.titleView = stackView
}
}
Si vous recherchez un code Objective-C de la solution susmentionnée
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;
Merci pour la réponse @RajanMaheshwari
Si quelqu'un a le problème où le titre est mal aligné lorsque le texte du sous-titre est plus long que le texte du titre, j'ai ajouté le code suivant à la réponse de Rajan ci-dessous, juste en dessous du libellé subtitleLabel:
// 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
}
J'espère que cela aide quelqu'un qui a rencontré le même problème que moi
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
}
}
Utilisation:
import UIKit
class ViewController: UIViewController {
private var navigationTitleView = NavigationTitleView()
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.titleView = navigationTitleView
navigationTitleView.set(title: "title", subTitle: "subTitle")
}
}
Une autre solution, utilisant uniquement les étiquettes one et NSAttributedString
pour différencier le titre du sous-titre (avec différentes tailles de police, poids, couleurs, etc.). Supprime le problème de l'alignement différent des étiquettes.
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 personnalisé basé en partie sur https://stackoverflow.com/a/34298491/3918865
J'ai bien aimé la réponse de @ user2325031, mais j'ai constaté qu'il n'était pas nécessaire de dimensionner les étiquettes pour l'adapter et de définir le cadre. J'ai également défini l'alignement de stackView sur .center selon la suggestion 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
}
}