在 UILabel 上使用捏合手势调整字体大小和标签框架?
Resize font along with frame of label using pinch gesture on UILabel?
每当用户使用捏合手势调整标签大小时,平滑地增大或减小字体大小。
备注
- 不影响字体质量
- 不仅变换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)
}
}
}
每次 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
}
}
}
你可以试试:
1 - 设置此标签的最大字体大小
2 - 将换行符设置为截尾
3 - 将自动收缩设置为最小字体大小(最小尺寸)
我用下面的代码解决了这个问题,它在所提到的各个方面都运行良好,类似于 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
}
每当用户使用捏合手势调整标签大小时,平滑地增大或减小字体大小。
备注
- 不影响字体质量
- 不仅变换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)
}
}
}
每次 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
}
}
}
你可以试试:
1 - 设置此标签的最大字体大小
2 - 将换行符设置为截尾
3 - 将自动收缩设置为最小字体大小(最小尺寸)
我用下面的代码解决了这个问题,它在所提到的各个方面都运行良好,类似于 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
}