【问题标题】:Get NSTextField contents to scale获取 NSTextField 内容以进行缩放
【发布时间】:2010-05-25 21:34:55
【问题描述】:

我怎样才能让文本比例适合我给它的范围?

【问题讨论】:

    标签: cocoa scale nstextfield


    【解决方案1】:

    我过去做过类似的事情。

    -(void)calcFontSizeToFitRect:(NSRect)r {
        float targetWidth = r.size.width - xMargin;
        float targetHeight = r.size.height - yMargin;
        
        // the strategy is to start with a small font size and go larger until I'm larger than one of the target sizes
        int i;
        for (i=minFontSize; i<maxFontSize; i++) {
            NSDictionary* attrs = [[NSDictionary alloc] initWithObjectsAndKeys:[NSFont fontWithName:currentFontName size:i], NSFontAttributeName, nil];
            NSSize strSize = [stringValue sizeWithAttributes:attrs];
            [attrs release];
            if (strSize.width > targetWidth || strSize.height > targetHeight) break;
        }
        [self setCurrentFontSize:(i-1)];
    }
    

    stringValue 变量是您想要调整大小的文本。 xMarginyMargin 变量用于您想要的间距。 minFontSizemaxFontSize 变量限制了您想要的大小。

    【讨论】:

    • 多行文本字段的任何解决方案?我将不胜感激!
    • maxFontSize 很大,并且字体不需要恰好适合容器的最大磅值时,您可以获得更好的性能(例如,当用户正在调整窗口的大小),方法是将循环变量设为浮点数而不是整数,并通过将其自身乘以 1.1 之类的因子而不是将其增加一个平面 1 来递增它。
    • 另外,在 2021 年末,我们仍然需要为此编写自定义代码,这有点奇怪,因为 NSTextField 没有提供这种开箱即用的功能,例如 @987654332 @ 使用其 adjustsFontSizeToFitWidth 属性 (stackoverflow.com/a/4865577/12484)。
    【解决方案2】:

    这个取自 iOS 的解决方案效果很好。但是,需要注意的一点:如果您以编程方式进行设置,则需要使用具有宽度和高度的矩形来初始化 NSTextfield,否则 bounds 返回 0。

    这也是我找到此解决方案的链接: https://medium.com/@joncardasis/dynamic-text-resizing-in-swift-3da55887beb3

    extension NSFont {
      /**
       Will return the best font conforming to the descriptor which will fit in the provided bounds.
       */
      static func bestFittingFontSize(for text: String, in bounds: CGRect, fontDescriptor: NSFontDescriptor, additionalAttributes: [NSAttributedString.Key: Any]? = nil) -> CGFloat {
        let constrainingDimension = min(bounds.width, bounds.height)
        let properBounds = CGRect(origin: .zero, size: bounds.size)
        var attributes = additionalAttributes ?? [:]
    
        let infiniteBounds = CGSize(width: CGFloat.infinity, height: CGFloat.infinity)
        var bestFontSize: CGFloat = constrainingDimension
    
        for fontSize in stride(from: bestFontSize, through: 0, by: -1) {
          let newFont = NSFont(descriptor: fontDescriptor, size: fontSize)
          attributes[.font] = newFont
    
          let currentFrame = text.boundingRect(with: infiniteBounds, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: attributes, context: nil)
    
          if properBounds.contains(currentFrame) {
            bestFontSize = fontSize
            break
          }
        }
        return bestFontSize
      }
    
      static func bestFittingFont(for text: String, in bounds: CGRect, fontDescriptor: NSFontDescriptor, additionalAttributes: [NSAttributedString.Key: Any]? = nil) -> NSFont {
        let bestSize = bestFittingFontSize(for: text, in: bounds, fontDescriptor: fontDescriptor, additionalAttributes: additionalAttributes)
        // TODO: Safely unwrap this later
        return NSFont(descriptor: fontDescriptor, size: bestSize)!
      }
    }
    
    extension NSTextField {
      /// Will auto resize the contained text to a font size which fits the frames bounds.
      /// Uses the pre-set font to dynamically determine the proper sizing
      func fitTextToBounds() {
        guard let currentFont = font else {
          return
        }
        let text = stringValue
        let bestFittingFont = NSFont.bestFittingFont(for: text, in: bounds, fontDescriptor: currentFont.fontDescriptor, additionalAttributes: basicStringAttributes)
        font = bestFittingFont
      }
    
      private var basicStringAttributes: [NSAttributedString.Key: Any] {
        var attribs = [NSAttributedString.Key: Any]()
    
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.alignment = self.alignment
        paragraphStyle.lineBreakMode = self.lineBreakMode
        attribs[.paragraphStyle] = paragraphStyle
    
        return attribs
      }
    }
    

    【讨论】:

      【解决方案3】:
      For me label.adjustsFontSizeToFitWidth = true reduces the font size. 
      
      with...
      
      
      lazy var labelContainerView: UIView =
      {   let view = UIView()
          return  view.labelContainerView(view: view, label)   }()
      
      
      extension UIView {
      func anchor(   top: NSLayoutYAxisAnchor?,
                          left: NSLayoutXAxisAnchor?,
                          bottom: NSLayoutYAxisAnchor?,
                          right: NSLayoutXAxisAnchor?,
                          paddingTop: CGFloat,
                          paddingLeft: CGFloat,
                          paddingBottom: CGFloat,
                          paddingRight: CGFloat,
                          width: CGFloat,
                          height: CGFloat     )
      
          {   translatesAutoresizingMaskIntoConstraints = false
      
              if let top = top {   self.topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true   }
      
              if let left = left {   self.leftAnchor.constraint(equalTo: left, constant: paddingLeft).isActive = true   }
      
              if let bottom = bottom {   self.bottomAnchor.constraint(equalTo: bottom, constant: -paddingBottom).isActive = true   }
      
              if let right = right {   self.rightAnchor.constraint(equalTo: right, constant: -paddingRight).isActive = true   }
      
              if width != 0 {   widthAnchor.constraint(equalToConstant: width).isActive = true   }
      
              if height != 0 {   heightAnchor.constraint(equalToConstant: height).isActive = true    }
          }
      }
      
      
      func labelContainerView(view: UIView, _ label: UILabel) -> UIView
      
          {   view.addSubview(label)
              label.anchor(top: view.topAnchor, left: view.leftAnchor, bottom: nil, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
              label.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
              label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
      
              return view
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-08
        • 1970-01-01
        • 2017-04-08
        • 2015-04-28
        • 2020-10-21
        • 1970-01-01
        • 2014-11-24
        • 1970-01-01
        相关资源
        最近更新 更多