Get NSTextField contents to scale

前端 未结 3 1829
再見小時候
再見小時候 2020-12-01 05:43

How can I have the text scale to fit the bounds I gave it?

3条回答
  •  鱼传尺愫
    2020-12-01 06:26

    This solution appropriated from iOS works quite well. However, one thing to note: If you are setting this up programatically, you need to initialise your NSTextfield with a rect that has a width and height, otherwise the bounds returns 0.

    Also here's the link where I found this solution: 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
      }
    }
    

提交回复
热议问题