首页 文章

在Xcode的导航栏控制器的 Headers 下添加字幕

提问于
浏览
31

所以我想在导航控制器的导航栏中添加 Headers 下的“副 Headers ” .

到目前为止,我查找的大部分内容都要我使用CGRect . 我不知道那是什么,这听起来像是想要我创建一个全新的视图而不是我想做的事情 .

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

我发现的最接近的事情是在堆栈溢出时发布,这是链接:

Create a subtitle in navigationbar

显然去年这有效,但现在我得到错误,它在我的viewDidLoad ...

我试过这个:

self.navigationController?.navigationItem.prompt =“Subtitle Here”

这是唯一不会显示任何错误但仍然不起作用的东西 . 它实际上什么都不做 . 在运行时至少没有任何可见的东西 .

另一方面,swift是首选 . 谢谢!

9 回答

  • 3

    虽然有一个解决方案,但它有一些已知的问题

    解决方案是编写这样的函数

    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 中使用此功能进行自定义导航 Headers 视图

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

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

    最终结果
    enter image description here

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

  • 0

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

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

    非常感谢您的回答! @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
        }
    

    再次感谢您的回复!

  • 1

    @ 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
      }
    }
    
  • 43

    如果有人在寻找上述解决方案的 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;
    
  • 2

    谢谢@RajanMaheshwari的答案

    如果有任何人在副 Headers 文本长于 Headers 文本时出现 Headers 未对齐的问题,我将以下代码添加到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
    }
    

    希望这可以帮助遇到与我相同问题的人

  • 3

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

    enter image description here

  • 11

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

    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部分基于https://stackoverflow.com/a/34298491/3918865

  • 2

    我真的很喜欢@ 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
        }
    
    }
    

相关问题