Get NSTextField contents to scale

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

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

相关标签:
3条回答
  • 2020-12-01 06:19

    I've done something like this in the past.

    -(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 = [string sizeWithAttributes:attrs];
            [attrs release];
            if (strSize.width > targetWidth || strSize.height > targetHeight) break;
        }
        [self setCurrentFontSize:(i-1)];
    }
    

    The string variable is the text you want sized. The xMargin and yMargin variables are for spacing that you want. The minFontSize and maxFontSize variables give limits to how small or large you want to go.

    0 讨论(0)
  • 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
      }
    }
    
    0 讨论(0)
  • 2020-12-01 06:26
    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
        }
    }
    
    0 讨论(0)
提交回复
热议问题