我正在使用下面修改的UITapGestureRecognizer,以便其他人可以复制并粘贴以查看与我相同的输出。
extension UITapGestureRecognizer {
func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool {
// Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
let layoutManager = NSLayoutManager()
let textContainer = NSTextContainer(size: CGSize.zero)
//let mutableAttribString = NSMutableAttributedString(attributedString: label.attributedText!)
//mutableAttribString.addAttributes([NSAttributedString.Key.font: label.font!], range: NSRange(location: 0, length: label.attributedText!.length))
let textStorage = NSTextStorage(attributedString: label.attributedText!)
//let textStorage = NSTextStorage(attributedString: mutableAttribString)
// Configure layoutManager and textStorage
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
// Configure textContainer
textContainer.lineFragmentPadding = 0.0
textContainer.lineBreakMode = label.lineBreakMode
textContainer.maximumNumberOfLines = label.numberOfLines
let labelSize = label.bounds.size
print("LabelSize=",labelSize)
textContainer.size = labelSize
print("TextContainerSize=",textContainer.size)
// Find the tapped character location and compare it to the specified range
let locationOfTouchInLabel = self.location(in: label)
print("LocationOfTouchInLabel=",locationOfTouchInLabel)
let textBoundingBox = layoutManager.usedRect(for: textContainer)
print("TextBoundingBox=",textBoundingBox)
//let textContainerOffset = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
//(labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);
let textContainerOffset = CGPoint(x: (labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x, y: (labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y)
print("textContainerOffset",textContainerOffset)
//let locationOfTouchInTextContainer = CGPointMake(locationOfTouchInLabel.x - textContainerOffset.x,
// locationOfTouchInLabel.y - textContainerOffset.y);
let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - textContainerOffset.x, y: locationOfTouchInLabel.y - textContainerOffset.y)
print("LocationOfTouchInTextContainer",locationOfTouchInTextContainer)
let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
print("IndexOfCharacter=",indexOfCharacter)
print("TargetRange=",targetRange)
return NSLocationInRange(indexOfCharacter, targetRange)
}
}
我设置了标签,以便像其他答案所说的那样检测点击次数:
formulaLabel.addGestureRecognizer(UITapGestureRecognizer(target:self, action: #selector(tapLabel(gesture:))))
已设置为归因。
如果很重要,我有以下代码可以对文本进行动画处理。
func doFormulaAnimation(){
//animTimer = Timer.scheduledTimer(withTimeInterval: 0.3, repeats: true, block: {_ in
//Draw correct formula based on mode.
var formula = ""
var highlight_ranges:[NSRange] = []
if(stateController?.tdfvariables.ebrtMode == true){
formulaLabel.numberOfLines = 1
formula = "BED = N * d * [ RBE + ( d / (α/β) ) ]"
self.formulaLabel.attributedText = NSMutableAttributedString(string: formula, attributes: [ NSAttributedString.Key.foregroundColor: UIColor.label ])
if(self.dosePerFractionSelected==true){
highlight_ranges.append(NSRange(location: 10, length: 1))
highlight_ranges.append(NSRange(location: 24, length: 1))
}
if(self.alphaBetaSelected==true){
highlight_ranges.append(NSRange(location: 29, length: 3))
}
if(self.totalDoseSelected==true){
highlight_ranges.append(NSRange(location: 6, length: 5))
}
if(self.numFractionsSelected==true){
highlight_ranges.append(NSRange(location: 6, length: 1))
}
}
if(stateController?.tdfvariables.ldrMode == true){
formulaLabel.numberOfLines = 3
formula = "BED = R * T * [RBE + (( g * R * T) / (α/β) ) ]\ng = ( 2 / μT ) * ( 1 - ( ( 1 - exp(-μT) / μT ) )\nμ = 0.693 / Thalf repair"
}
if(stateController?.tdfvariables.permMode == true){
formulaLabel.numberOfLines = 2
formula = "BED = ( R0 / L ) * [ RBE + ( R0 / ( ( u + L) * (α/β) ) ) ]\n"
}
UIView.transition(with: self.formulaLabel, duration: 0.5, options: .transitionCrossDissolve, animations: {
let colorAttribute = [ NSAttributedString.Key.foregroundColor: UIColor.label ]
let attributedTextFormula = NSMutableAttributedString(string: formula, attributes: colorAttribute)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 6
paragraphStyle.lineBreakMode = .byTruncatingTail
//paragraphStyle.alignment = .center
attributedTextFormula.addAttribute(
.paragraphStyle,
value: paragraphStyle,
range: NSRange(location: 0, length: attributedTextFormula.length
))
self.formulaLabel.attributedText = attributedTextFormula
//
}, completion: { finished in
print("finished first transition")
UIView.transition(with: self.formulaLabel, duration: 0.5, options: .transitionCrossDissolve, animations: {
let colorAttribute = [ NSAttributedString.Key.foregroundColor: UIColor.label ]
let attributedTextFormula = NSMutableAttributedString(string: formula, attributes: colorAttribute)
for range in highlight_ranges {
attributedTextFormula.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red, range: range)
}
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 6
paragraphStyle.lineBreakMode = .byTruncatingTail
//paragraphStyle.alignment = .center
attributedTextFormula.addAttribute(
.paragraphStyle,
value: paragraphStyle,
range: NSRange(location: 0, length: attributedTextFormula.length
))
self.formulaLabel.attributedText = attributedTextFormula
//self.formulaLabel.addInterlineSpacing(spacingValue: 1)
}, completion: { finished in
print("finished second transition")
})
})
}
[上面的代码演示了我如何相应地创建NSMutableString并相应地设置段落样式和行间距(我预感这可能是问题所在,但不确定如何进行测试等等)...
最后我有了我的水龙头标签功能
@IBAction func tapLabel(gesture: UITapGestureRecognizer) {
guard let text = formulaLabel.attributedText?.string else {
return
}
let AB_Range = text.range(of: "(α/β)")
//let AB_Range = NSRange(location: 29, length: 3)
if gesture.didTapAttributedTextInLabel(label: formulaLabel, inRange: NSRange(AB_Range!, in: text)) {
print("Tapped a/b")
} else {
print("Tapped none")
}
}
目前,它没有轻敲正确的位置,但是在很大的程度上偏离了。在调试后,很明显为什么它不起作用,但是我不确定如何修复代码或哪里出错了。
[当我像应按A / B那样单击时,我应该将此作为调试信息。
LabelSize= (315.0, 43.0)
TextContainerSize= (315.0, 43.0)
LocationOfTouchInLabel= (266.0, 28.0)
TextBoundingBox= (0.0, 0.0, 185.373046875, 13.8)
textContainerOffset (64.8134765625, 14.6)
LocationOfTouchInTextContainer (201.1865234375, 13.4)
IndexOfCharacter= 36
TargetRange= {28, 5}
Tapped none
它计算文本边界框或textcontaineroffset或touchintextcontainer的位置的部分是最有可能的错误点,但我不确定是哪一个,因为这很难理解。
我可以告诉它它不能正常工作,因为在我的字符串中,它不在结尾处,并且无论单击什么位置,它总是显示indexofcharacter = 36,这意味着它不能使用我上面提到的变量之一正确地计算出东西。
如果他们知道为什么这样不起作用,可以提供任何帮助。
为了让您知道文本的外观,我在下面向您展示。我的最终目标是做到这一点,这样我就可以单击公式中的各个部分以显示值,因此可以说可单击的链接。
更新::
我忘了提到我在更新UITapGestureRecognizer并添加以下行时:
let mutableAttribString = NSMutableAttributedString(attributedString: label.attributedText!)
mutableAttribString.addAttributes([NSAttributedString.Key.font: label.font!], range: NSRange(location: 0, length: label.attributedText!.length))
并将其设置为文本存储,let textStorage = NSTextStorage(attributedString: mutableAttribString)
我似乎确实看到数字有所改进,但仍遥遥无期。
LabelSize= (315.0, 43.0)
TextContainerSize= (315.0, 43.0)
LocationOfTouchInLabel= (269.0, 25.5)
TextBoundingBox= (7.505859375, 0.0, 299.98828125, 42.9609375)
textContainerOffset (0.0, 0.01953125)
LocationOfTouchInTextContainer (269.0, 25.48046875)
IndexOfCharacter= 17
TargetRange= {28, 5}
Tapped none
您将注意到textboundingbox至少与标签大小更相似。我在某处读到一个问题,如果您使用的是不同的字体,可能就是这样,这就是为什么我尝试添加该字体以确保其正常工作的原因。
同样有趣的是,将其添加到UITapGestureRecognizer似乎也有帮助:
let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 6 paragraphStyle.lineBreakMode = .byTruncatingTail //paragraphStyle.alignment = .center mutableAttribString.addAttribute( .paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: mutableAttribString.length ))
[我注意到这样做时,文本边界框正确显示了0,0,而不是7.50
LabelSize= (315.0, 43.0) TextContainerSize= (315.0, 43.0) LocationOfTouchInLabel= (262.5, 31.0) TextBoundingBox= (0.0, 0.0, 299.98828125, 42.9609375) textContainerOffset (7.505859375, 0.01953125) LocationOfTouchInTextContainer (254.994140625, 30.98046875) IndexOfCharacter= 17 TargetRange= {28, 5} Tapped none
**主要更新*****
好消息!事实证明,font fix
是该修复程序的一部分,但是由于我具有使用最小字体大小启用的自动收缩和最大字体大小,因此它从未正确计算! 当我设置为固定字体大小时,一切正常!问题现在如何在启用自动收缩功能的情况下起作用?
请注意,您必须将大小设置为非常大的值才能证明其有效,例如我将我的尺寸设置为55,以便它相应地自动收缩,然后您会看到错误,如果默认大小较小,那么它似乎可以正常工作,这告诉我错误与大小最初可能很大有关?我正在使用下面修改的UITapGestureRecognizer,以便其他人可以复制并粘贴以查看与我相同的输出。扩展名UITapGestureRecognizer {func didTapAttributedTextInLabel(...
所以我终于找到了可以接受的答案。