Получить содержимое NSTextField в масштабе - PullRequest
8 голосов
/ 26 мая 2010

Как мне получить масштаб текста, чтобы он соответствовал границам, которые я ему дал?

Ответы [ 2 ]

21 голосов
/ 26 мая 2010

Я делал что-то подобное в прошлом.

-(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)];
}

Строковая переменная - это текст, размер которого вы хотите изменить. Переменные xMargin и yMargin предназначены для интервалов, которые вы хотите. Переменные minFontSize и maxFontSize задают пределы того, насколько маленьким или большим вы хотите идти.

0 голосов
/ 22 мая 2019

Это решение, присвоенное iOS, работает довольно хорошо. Однако следует отметить одну вещь: если вы настраиваете это программно, вам нужно инициализировать поле NSText с прямоугольником, имеющим ширину и высоту, в противном случае 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
  }
}
...