Resize font along with frame of label using pinch gesture on UILabel?

℡╲_俬逩灬. 提交于 2019-12-11 06:41:50

问题


Increase or decrease font size smoothly whenever user resize label using pinch gesture on it.

Note

  • Without compromising quality of font
  • Not only transforming the scale of UILabel
  • With support of multiline text
  • Rotation gesture should work proper with pinch gesture
  • Reference: SnapChat or Instagram Text Editor tool

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)
        }
    }
}

回答1:


I solved the problem with following code which is working fine with every aspect which are mentioned in question, similar to Snapchat and 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:


Call following method every time after UILabel size changes.

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:


you can try:

1 - Set maximum font size for this label

2 - Set line break to Truncate Tail

3 - Set Autoshrink to Minimum font size (minimum size)



来源:https://stackoverflow.com/questions/54213119/resize-font-along-with-frame-of-label-using-pinch-gesture-on-uilabel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!