【问题标题】:Add subtitle under the title in navigation bar controller in Xcode在Xcode导航栏控制器的标题下添加字幕
【发布时间】:2016-07-28 02:07:32
【问题描述】:

所以我想在导航控制器导航栏的标题下添加一个“副标题”。

到目前为止,我查找的大部分内容都希望我使用 CGRect。我不太清楚那是什么,听起来它想让我创建一个全新的视图,这不是我想做的。

我的问题是,有没有一种点法可以轻松添加字幕视图?

我发现的最接近的东西是在堆栈溢出上发布的,这是链接:

Create a subtitle in navigationbar

显然去年这行得通,但现在我遇到了错误,它在我的 viewDidLoad...

我试过了:

self.navigationController?.navigationItem.prompt = "这里的字幕"

这是唯一不会显示任何错误但仍然不起作用的东西。它实际上什么也没做。至少在运行时看不到任何东西。

顺便说一句,swift 是首选。谢谢!

【问题讨论】:

  • 你试过self.navigationItem.prompt = "Subtitle"吗?
  • @tktsubota 这将使字幕在标题上方而不是在标题下方
  • @RajanMaheshwari 是的,我做了一个测试,发现了。
  • @tktsubota 你在开玩笑吗?不是字幕,是导航栏上方的一个新的独立栏,有自己的标题,这样你就有了两个栏,没用!
  • 它将帮助你所有现有的场景stackoverflow.com/questions/37409260/…

标签: swift uinavigationcontroller uinavigationbar uinavigationitem


【解决方案1】:

这是我在扩展上使用堆栈视图的版本。

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
        stackView.alignment = .center
        
        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
    }
}

【讨论】:

  • 从导航控制器推送任何解决方法时,标题和副标题从左侧滑动到中心
  • 对我来说,这是更清晰的答案,它没有幻数作为第一个答案。我只会在你设置轴之后添加stackView.alignment = .center,否则如果字幕更大,它不会显示完全居中。此外,我会删除对sizeToFit() 的最后两个调用,因为您在标签上调用了它们。
  • 默认标题是否也有恒定的字体值 17?
【解决方案2】:

虽然有解决方案,但存在一些已知问题

解决办法就是写一个这样的函数

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
}

viewDidLoad中使用该函数自定义导航标题视图

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

唯一已知的问题是,如果字幕变得非常大,就会发生错位。

最终结果

来源:https://gist.github.com/nazywamsiepawel/0166e8a71d74e96c7898

【讨论】:

  • 它的代码比我预期的要多得多,但它确实有效。我真的希望苹果能增加一个更简单的方法。字幕看起来不像是遥不可及的东西……哈哈
  • 非常感谢! :) @rajan
  • 我需要这样的东西,如果标题是空白的,那么标题应该在中心。我必须在聊天应用程序中实现。如果用户开始输入,则显示字幕。欲了解更多信息,请参阅 WhatsApp。
  • 从导航控制器推送任何解决方法时,标题和副标题从左侧滑动到中心@naveed
  • 上述解决方案使两个文本居中,在我的情况下它的工作
【解决方案3】:

@iosjillian 的 Swift 4 扩展效果很好,添加了更多内容来尊重栏的外观和用户字体偏好:

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
  }
}

【讨论】:

    【解决方案4】:

    非常感谢您的回答! @RajanMaheshwari

    除了使用 widthDiff 进行的 if 语句之外,您的编码工作完美。

    我稍微调整了一下,一切都很顺利。

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

    再次感谢您的回复!

    【讨论】:

    • 很好的修复!也必须这样做。
    【解决方案5】:

    我真的很喜欢@user2325031 的回答,但发现不需要调整标签大小以适应和设置框架。根据@GerardoMR 的建议,我还将 stackView 的对齐方式设置为 .center。

    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
        }
    
    }
    

    【讨论】:

      【解决方案6】:

      如果有人在寻找上述解决方案的Objective-C 代码:

         UILabel *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;
      

      【讨论】:

        【解决方案7】:

        感谢@RajanMaheshwari 的回答

        如果有人在字幕文本长于标题文本时遇到标题未对齐的问题,我将以下代码添加到上面 Rajan 的答案中,就在 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
        }
        

        希望对遇到和我一样问题的人有所帮助

        【讨论】:

        • 根据上面的@GerardoMR 评论——您可以使用 UIStackView 设置将标题/副标题居中:stackView.alignment = .center
        【解决方案8】:

        另一种解决方案,仅使用 one 标签和NSAttributedString 来区分标题和副标题(具有不同的字体大小、粗细、颜色等)。消除了不同标签对齐的问题。

        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
            }
        }
        

        部分基于https://stackoverflow.com/a/34298491/3918865的自定义titleView

        【讨论】:

          【解决方案9】:

          斯威夫特 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
          
              }
          
          }
          

          用途:

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

          【讨论】:

            猜你喜欢
            • 2020-05-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-02-21
            • 1970-01-01
            • 2019-12-01
            相关资源
            最近更新 更多