【问题标题】:Resize font along with frame of label using pinch gesture on UILabel?使用UILabel上的捏合手势调整字体和标签框架的大小?
【发布时间】:2019-01-17 17:37:46
【问题描述】:

当用户使用捏合手势调整标签大小时,平滑地增加或减小字体大小。

注意

  • 不影响字体质量
  • 不仅改变了 UILabel 的规模
  • 支持多行文本
  • 旋转手势应与捏合手势正常工作
  • 参考:SnapChat 或 Instagram 文本编辑器工具

extension String {
    func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: UIFont(name: font.fontName, size: font.pointSize)!], context: nil)
        return ceil(boundingBox.height)
    }

    func width(withConstrainedHeight height: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: UIFont(name: font.fontName, size: font.pointSize)!], context: nil)
        return ceil(boundingBox.width)
    }
}

func resizeLabelToText(textLabel : UILabel)
{
    let labelFont = textLabel.font
    let labelString = textLabel.text
    let labelWidth : CGFloat = labelString!.width(withConstrainedHeight: textLabel.frame.size.height, font: labelFont!)
    let labelHeight : CGFloat = labelString!.height(withConstrainedWidth: labelWidth, font: labelFont!)

    textLabel.frame = CGRect(x: textLabel.frame.origin.x, y: textLabel.frame.origin.y, width: labelWidth, height: labelHeight)
    textLabel.font = labelFont
}

func pinchedRecognize(_ pinchGesture: UIPinchGestureRecognizer) {
    guard pinchGesture.view != nil else {return}

    if (pinchGesture.view is UILabel) {
        let selectedTextLabel = pinchGesture.view as! UILabel

        if pinchGesture.state == .began || pinchGesture.state == .changed {
            let pinchScale = round(pinchGesture.scale * 1000) / 1000.0
            if (pinchScale < 1) {
                selectedTextLabel.font = selectedTextLabel.font.withSize(selectedTextLabel.font.pointSize - pinchScale)
            }
            else {
                selectedTextLabel.font = selectedTextLabel.font.withSize(selectedTextLabel.font.pointSize + pinchScale)
            }
            resizeLabelToText(textLabel: selectedTextLabel)
        }
    }
}

【问题讨论】:

  • 您应该edit 您的问题以minimal reproducible example 的形式包含所有相关代码。没有那个,你的问题在这里被认为是题外话
  • @FE_Tech 更新了细节。

标签: ios swift uilabel pinchzoom uipinchgesturerecognizer


【解决方案1】:

我用下面的代码解决了这个问题,这些代码在提到的各个方面都可以正常工作,类似于 Snapchat 和 Instagram:

var pointSize: CGFloat = 0
@objc func pinchRecoginze(_ pinchGesture: UIPinchGestureRecognizer) {
    guard pinchGesture.view != nil else {return}

    let view = pinchGesture.view!
    if (pinchGesture.view is UILabel) {
        let textLabel = view as! UILabel

        if pinchGesture.state == .began {
            let font = textLabel.font
            pointSize = font!.pointSize

            pinchGesture.scale = textLabel.font!.pointSize * 0.1
        }
        if 1 <= pinchGesture.scale && pinchGesture.scale <= 10  {
            textLabel.font = UIFont(name: textLabel.font!.fontName, size: pinchGesture.scale * 10)

            resizeLabelToText(textLabel: textLabel)
        }
    }
}

func resizeLabelToText(textLabel : UILabel) {
    let labelSize = textLabel.intrinsicContentSize
    textLabel.bounds.size = labelSize
}

【讨论】:

  • 很棒的解决方案
【解决方案2】:

每次UILabel大小改变后调用下面的方法。

func labelSizeHasBeenChangedAfterPinch(_ label:UILabel, currentSize:CGSize){
        let MAX = 25
        let MIN = 8
        let RATE = -1
        for proposedFontSize in stride(from: MAX, to: MIN, by: RATE){
            let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
            let attribute = [NSAttributedString.Key.font:UIFont.systemFont(ofSize: CGFloat(proposedFontSize))]
            // let context = IF NEEDED ...
            let rect =  NSString(string: label.text ?? "").boundingRect(with: currentSize, options: options, attributes: attribute, context: nil)
            let labelSizeThatFitProposedFontSize = CGSize(width: rect.width , height: rect.height)
            if (currentSize.height > labelSizeThatFitProposedFontSize.height) && (currentSize.width > labelSizeThatFitProposedFontSize.width){
                DispatchQueue.main.async {
                    label.font = UIFont.systemFont(ofSize: CGFloat(proposedFontSize))
                }
                break
            }
        }
    }

【讨论】:

  • 我已经尝试过了,但没有按预期工作。捏缩放时字体变得模糊,并且也无法使用多行文本呈现正确的输出。
【解决方案3】:

你可以试试:

1 - 设置此标签的最大字体大小

2 - 设置换行符以截断尾部

3 - 将 Autoshrink 设置为最小字体大小(最小大小)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-01
    相关资源
    最近更新 更多