【问题标题】:How to resize Title in a navigation bar dynamically如何动态调整导航栏中标题的大小
【发布时间】:2013-02-04 01:54:29
【问题描述】:

我有一些视图显示在导航控制器中。其中两个视图的导航栏标题较长。

问题是当标题太长放不下时,会截断部分字符并添加“...”。

有什么方法可以告诉导航栏自动调整标题文本的大小以适应?

【问题讨论】:

标签: iphone uinavigationcontroller resize uinavigationbar autoresize


【解决方案1】:

在 ViewDidload 中使用了以下代码。

目标 C

self.title = @"Your TiTle Text";
UILabel* tlabel=[[UILabel alloc] initWithFrame:CGRectMake(0,0, 200, 40)];
tlabel.text=self.navigationItem.title;
tlabel.textColor=[UIColor whiteColor];
tlabel.font = [UIFont fontWithName:@"Helvetica-Bold" size: 30.0];
tlabel.backgroundColor =[UIColor clearColor];
tlabel.adjustsFontSizeToFitWidth=YES;
tlabel.textAlignment = NSTextAlignmentCenter;
self.navigationItem.titleView=tlabel;

斯威夫特版

self.title = "Your Title Text"
let tlabel = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
tlabel.text = self.title
tlabel.textColor = UIColor.white
tlabel.font = UIFont.systemFont(ofSize: 30, weight: .bold)
tlabel.backgroundColor = UIColor.clear
tlabel.adjustsFontSizeToFitWidth = true
tlabel.textAlignment = .center
self.navigationItem.titleView = tlabel

希望它对你有用。谢谢

【讨论】:

【解决方案2】:

已接受答案的 Swift 版本 + 将标签文本放在中心:

斯威夫特 2.3:

    self.title = "Your TiTle Text"
    let tlabel = UILabel(frame: CGRectMake(0, 0, 200, 40))
    tlabel.text = self.title
    tlabel.textColor = UIColor.whiteColor()
    tlabel.font = UIFont.boldSystemFontOfSize(17) //UIFont(name: "Helvetica", size: 17.0)
    tlabel.backgroundColor = UIColor.clearColor()
    tlabel.adjustsFontSizeToFitWidth = true
    tlabel.textAlignment = .Center
    self.navigationItem.titleView = tlabel

还有 Swift 3:

    self.title = "Your TiTle Text"
    let frame = CGRect(x: 0, y: 0, width: 200, height: 40)
    let tlabel = UILabel(frame: frame)
    tlabel.text = self.title
    tlabel.textColor = UIColor.white
    tlabel.font = UIFont.boldSystemFont(ofSize: 17) //UIFont(name: "Helvetica", size: 17.0)
    tlabel.backgroundColor = UIColor.clear
    tlabel.adjustsFontSizeToFitWidth = true
    tlabel.textAlignment = .center
    self.navigationItem.titleView = tlabel

【讨论】:

    【解决方案3】:

    如果你有一个视图添加到 titleView,并且你想调整视图大小,你可以使用这个代码(Swift 3)

    self.translatesAutoresizingMaskIntoConstraints = false
    self.layoutIfNeeded()
    self.sizeToFit()
    self.translatesAutoresizingMaskIntoConstraints = true
    

    【讨论】:

      【解决方案4】:

      这对我有用

      目标 C

      [UILabel appearanceWhenContainedInInstancesOfClasses:@[[UINavigationBar class]]].adjustsFontSizeToFitWidth = YES;
      

      斯威夫特版

      UILabel.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).adjustsFontSizeToFitWidth = true
      

      【讨论】:

      • 又短又甜!它有效。
      • 在 iOS 15 上测试并使用 largeTitles。
      【解决方案5】:

      以上解决方案都不适合我。 但是我通过使用提供答案的不同元素找到了一个解决方案,它在 Swift 2 中并且非常优雅,因为每次更改标签时它都不需要任何自定义代码,它只是在标题上使用属性观察器。

      请注意,在我的例子中,我在导航栏的左侧有一个后退按钮,它将文本置于屏幕中心之外,为了解决这个问题,我使用了属性文本和 tailIndent。以下代码中的所有 cmets/info :

      class VCHowToTopic : UIViewController {
      
      
          //add handlers so that any manipulation of the title is caught and transferred to the custom drawn UILabel
          override var title : String? {
              set {
                  super.title = newValue
                  configureTitleView()
              }
              get {
                  return super.title
              }
          }
      
          //MARK: - lifecycle
      
      
          func configureTitleView() {
              //some large number that makes the navigationbar schrink down our view when added
              let someVeryLargeNumber = CGFloat(4096)
              //create our label
              let titleLabel = UILabel(frame: CGRect(x: 0, y: 0, width: someVeryLargeNumber, height: someVeryLargeNumber))
              //0 means unlimited number of lines
              titleLabel.numberOfLines = 0
              //define style of the text (we will be using attributed text)
              let style = NSMutableParagraphStyle()
              style.alignment = .Center
              //top compensate for the backbutton which moves the centered text to the right side of the screen
              //we introduce a negative tail indent, the number of 56 has been experimentally defined and might
              //depend on the size of your custom back button (if you have one), mine is 22x22 px
              style.tailIndent = -56
              //create attributed text also with the right color
              let attrText = NSAttributedString(string: title!, attributes: [NSParagraphStyleAttributeName : style,
                  NSForegroundColorAttributeName : UIColor.whiteColor()])
              //configure the label to use the attributed text
              titleLabel.attributedText = attrText
              //add it as the titleview
              navigationItem.titleView = titleLabel
          }
      
      
      }
      

      【讨论】:

      • CGRect(x: 0, y: 0, width: someVeryLargeNumber, height: someVeryLargeNumber) 是使视图在 Title 中可见的关键
      【解决方案6】:

      您可以将 UILabel 创建为 UINavigationItem 的 titleView 并将其设置为 adjustsFontSizeToFitWidthtrue

      class MyViewController: UIViewController {
          override var title: String? {
              didSet {
                  (self.navigationItem.titleView as? UILabel)?.text = self.title
              }
          }
          
          override func viewDidLoad() {
              super.viewDidLoad()
      
              self.navigationItem.titleView = UILabel().apply {
                  $0.font = .boldSystemFont(ofSize: 18)
                  $0.minimumScaleFactor = 0.5
                  $0.adjustsFontSizeToFitWidth = true
                  $0.text = self.title
              }
          }
      }
      

      易于使用:

      myViewController.title = "This is a long title, but don’t worry."
      

      上面代码中的apply闭包是个小技巧,目的是为了让编程体验更好。还有一个with 闭包。推荐给大家。

      protocol ScopeFunc {}
      
      extension ScopeFunc {
          @inline(__always) func apply(_ block: (Self) -> ()) -> Self {
              block(self)
              return self
          }
      
          @inline(__always) func with<R>(_ block: (Self) -> R) -> R {
              return block(self)
          }
      }
      
      extension NSObject: ScopeFunc {}
      

      【讨论】:

        【解决方案7】:

        Swift 5 和 iOS 13 / iOS 14

        如果您在 Swift 5 和 iOS 13 中有一个大标题,上述答案将不起作用,因为它们只是在您的导航栏中添加了另一个标题。相反,您可以在需要时使用 largeTitleTextAttributes 属性(自 iOS 11 起可用)来缩小标题。
        假设您已经通过故事板或代码设置了大标题,您可以使用以下方法:

        private func configureNavigationTitle(_ title: String) {
                let tempLabel = UILabel()
                tempLabel.font = UIFont.systemFont(ofSize: 34, weight: .bold)
                tempLabel.text = title
        
                if tempLabel.intrinsicContentSize.width > UIScreen.main.bounds.width - 30 {
                    var currentTextSize: CGFloat = 34
                    for _ in 1 ... 34 {
                        currentTextSize -= 1
                        tempLabel.font = UIFont.systemFont(ofSize: currentTextSize, weight: .bold)
                        if tempLabel.intrinsicContentSize.width < UIScreen.main.bounds.width - 30 {
                            break
                        }
                    }
                    navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.font : UIFont.systemFont(ofSize: currentTextSize, weight: .bold)]
                }
                self.title = title
            }
        

        所以本质上,我们使用辅助标签来获取标题的宽度,然后我们将缩小字体大小,直到标题适合我们的导航栏。 从viewDidLoad() 拨打电话:

        override func viewDidLoad() {
                super.viewDidLoad(
                configureNavigationTitle("A very long title which fits perfectly fine")
            }
        

        【讨论】:

          【解决方案8】:

          您需要使用uilabel自定义导航栏标题视图并提供调整字体大小..

              [self.navigationItem setTitleView:<"Include any UI View subclass">];
          

          【讨论】:

            【解决方案9】:

            这是 Swift 中的一个示例,它也允许多行。使用PureLayout 简化自动布局。

            override func viewDidLoad() {
              super.viewDidLoad()
              configureTitleView()
            }
            
            func configureTitleView() {
              let titleLabel = UILabel()
              titleLabel.numberOfLines = 0
              titleLabel.textAlignment = .Center
              titleLabel.font = UIFont.boldSystemFontOfSize(17.0)
              titleLabel.text = searchLoc.mapItem.name
              navigationItem.titleView = titleLabel
              titleLabel.autoPinEdgesToSuperviewMargins() // PureLayout method
              titleLabel.adjustsFontSizeToFitWidth = true
            }
            

            还有一个用法示例:

            【讨论】:

            • 无法正常工作,因为当调用 titleLabel.autoPinEdgesToSuperviewMargins 时,titleLabel 的超级视图(仍然)为 nil,因此设置了约束断言。 (xcode 7.3, IOS9)
            【解决方案10】:

            Swift 4 和 iOS 13

            添加这个以便我未来的自己可以找到它。由于某种原因添加到 titleView 的视图不喜欢自动调整大小。所以你必须手动完成。

            示例

            (navigationItem.titleView as? UILabel)?.text = "A longer string..." // label not resized and text is cut off
            

            解决方案

            navigationItem.titleView?.translatesAutoresizingMaskIntoConstraints = false
            navigationItem.titleView?.setNeedsLayout()
            navigationItem.titleView?.layoutIfNeeded()
            navigationItem.titleView?.translatesAutoresizingMaskIntoConstraints = true
            

            感谢@Paolo Musolino 带领我来到这里。

            【讨论】:

              猜你喜欢
              • 2014-02-23
              • 2018-01-19
              • 1970-01-01
              • 1970-01-01
              • 2016-06-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多