如何将函数调用(不是超链接)添加到 UILabel 中的 NSAttributedString 的一部分?
Posted
技术标签:
【中文标题】如何将函数调用(不是超链接)添加到 UILabel 中的 NSAttributedString 的一部分?【英文标题】:How to add function-call (not hyperlink) to part of an NSAttributedString in a UILabel? 【发布时间】:2017-02-24 08:02:59 【问题描述】:我需要在文本的某些部分添加一些 tapGestures,那就是在 UILabel 中。它似乎能够创建超链接 - 所以我猜它也可以进行函数调用,但我只是不知道该怎么做。
这是我的代码:
let regularFont = UIFont(name: Constants.robotoRegular, size: 13)!
let att1 = [NSFontAttributeName: regularFont]
let turqoiseFont = UIFont(name: Constants.robotoBold, size: 13)!
let att2 = [NSFontAttributeName: turqoiseFont]
let attString1 = NSMutableAttributedString(string: "By creating a profile, I accept ", attributes: att1)
attString1.addAttribute(NSForegroundColorAttributeName, value: UIColor.darkGrayColor(), range: NSMakeRange(0, attString1.length))
let attString2 = NSMutableAttributedString(string: "Terms and Conditions ", attributes: att2)
attString2.addAttribute(NSForegroundColorAttributeName, value: Colors.loginButtonColor, range: NSMakeRange(0, attString2.length))
let attString3 = NSMutableAttributedString(string: "and ", attributes: att1)
attString3.addAttribute(NSForegroundColorAttributeName, value: UIColor.darkGrayColor(), range: NSMakeRange(0, attString3.length))
let attString4 = NSMutableAttributedString(string: "Private Policy.", attributes: att2)
attString4.addAttribute(NSForegroundColorAttributeName, value: Colors.loginButtonColor, range: NSMakeRange(0, attString4.length))
let index = "\(attString1.string.endIndex)"
attString1.insertAttributedString(attString4, atIndex: Int(index)!)
attString1.insertAttributedString(attString3, atIndex: Int(index)!)
attString1.insertAttributedString(attString2, atIndex: Int(index)!)
termsAndConditionLabel.attributedText = attString1
我希望绿松石部件能够将用户带到条款和条件或私人政策。谁能帮我解决这个问题? :))
【问题讨论】:
【参考方案1】:我曾经做过同样的事情,但使用textView而不是UILabel,你应该创建自己的属性,并将它们添加到属性字符串,然后处理tap,这里有一些代码
你的代码和我的修改
let regularFont = UIFont(name: "HelveticaNeue", size: 13)!
let att1 = [NSFontAttributeName: regularFont]
let turqoiseFont = UIFont(name: "HelveticaNeue", size: 13)!
let att2 = [NSFontAttributeName: turqoiseFont]
let mattString : NSMutableAttributedString = NSMutableAttributedString()
let attString1 = NSMutableAttributedString(string: "By creating a profile, I accept ", attributes: att1)
attString1.addAttribute(NSForegroundColorAttributeName, value: UIColor.darkGray, range: NSMakeRange(0, attString1.length))
let attString2 = NSMutableAttributedString(string: "Terms and Conditions ", attributes: att2)
attString2.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: NSMakeRange(0, attString2.length))
let attString3 = NSMutableAttributedString(string: "and ", attributes: att1)
attString3.addAttribute(NSForegroundColorAttributeName, value: UIColor.darkGray, range: NSMakeRange(0, attString3.length))
let attString4 = NSMutableAttributedString(string: "Private Policy.", attributes: att2)
attString4.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: NSMakeRange(0, attString4.length))
mattString.append(attString1)
mattString.append(attString2)
mattString.append(attString3)
mattString.append(attString4)
let attributes = ["link" : "termsLink"]
let attributes2 = ["link" : "policyLink"]
let str : NSString = mattString.string as NSString
mattString.addAttributes(attributes, range: str.range(of: "Terms and Conditions"))
mattString.addAttributes(attributes2, range: str.range(of: "Private Policy"))
_textView.attributedText = mattString
_textView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.singleTap(tap:))))
和处理点击的函数
func singleTap(tap : UITapGestureRecognizer)
let layoutManager = _textView.layoutManager
let location = tap.location(in: _textView)
let index = layoutManager.characterIndex(for: location, in: _textView.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
if index > _textView.textStorage.length return
var range : NSRange = NSRange()
if let type = _textView.attributedText.attribute("link", at: index, effectiveRange: &range) as? String
if type == "termsLink"
//.. do smth
else
//.. do smth
更新:
这是我写的使用标签的类
https://github.com/barbados88/TapableLabel/blob/master/TapableLabel.swift
【讨论】:
太棒了!我使用了您的解决方案,并进行了一些调整 - 现在它的工作就像一个魅力!非常感谢【参考方案2】:我已经用 Swift 4 更改了Alexandr Kolesnik 他对UILabel
的回答。如果有人也想和UILabel
一起使用
let regularFontAttribute = [NSAttributedStringKey.font: UIFont(name: "Lato-Regular", size: 15.0)!]
let boldFontAttribute = [NSAttributedStringKey.font: UIFont(name: "Lato-Bold", size: 15.0)!]
let mattString : NSMutableAttributedString = NSMutableAttributedString()
let attString1 = NSMutableAttributedString(string: "By creating a profile, I accept ", attributes: regularFontAttribute)
let anotherAttribute1 = [NSAttributedStringKey.foregroundColor: UIColor.black]
attString1.addAttributes(anotherAttribute1, range: NSMakeRange(0, attString1.length))
let attString2 = NSMutableAttributedString(string: "Terms and Conditions ", attributes: boldFontAttribute)
let anotherAttribute2 = [NSAttributedStringKey.foregroundColor: UIColor.red]
attString2.addAttributes(anotherAttribute2, range: NSMakeRange(0, attString2.length))
let attString3 = NSMutableAttributedString(string: "and ", attributes: regularFontAttribute)
let anotherAttribute3 = [NSAttributedStringKey.foregroundColor: UIColor.black]
attString3.addAttributes(anotherAttribute3, range: NSMakeRange(0, attString3.length))
let attString4 = NSMutableAttributedString(string: "Private Policy.", attributes: boldFontAttribute)
let anotherAttribute4 = [NSAttributedStringKey.foregroundColor: UIColor.red]
attString4.addAttributes(anotherAttribute4, range: NSMakeRange(0, attString4.length))
mattString.append(attString1)
mattString.append(attString2)
mattString.append(attString3)
mattString.append(attString4)
let attributes: [NSAttributedStringKey : Any] = [NSAttributedStringKey(rawValue: "link") : "termsLink"]
let attributes2: [NSAttributedStringKey : Any] = [NSAttributedStringKey(rawValue: "link") : "policyLink"]
let str : NSString = mattString.string as NSString
mattString.addAttributes(attributes, range: str.range(of: "Terms and Conditions"))
mattString.addAttributes(attributes2, range: str.range(of: "Private Policy"))
self.attributedLabel.attributedText = mattString
self.attributedLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.singleTap(_:))))
self.attributedLabel.isUserInteractionEnabled = true
和 func 来处理点击和检测被点击的文本
@objc func singleTap(_ tap : UITapGestureRecognizer)
let attributedText = NSMutableAttributedString(attributedString: self.attributedLabel!.attributedText!)
attributedText.addAttributes([NSAttributedStringKey.font: self.attributedLabel!.font], range: NSMakeRange(0, (self.attributedLabel!.attributedText?.string.count)!))
// Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
let layoutManager = NSLayoutManager()
let textContainer = NSTextContainer(size: CGSize(width: (self.attributedLabel?.frame.width)!, height: (self.attributedLabel?.frame.height)!+100))
let textStorage = NSTextStorage(attributedString: attributedText)
// Configure layoutManager and textStorage
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
// Configure textContainer
textContainer.lineFragmentPadding = 0.0
textContainer.lineBreakMode = self.attributedLabel!.lineBreakMode
textContainer.maximumNumberOfLines = self.attributedLabel!.numberOfLines
let labelSize = self.attributedLabel!.bounds.size
textContainer.size = labelSize
let tapLocation = tap.location(in: self.attributedLabel)
// get the index of character where user tapped
let index = layoutManager.characterIndex(for: tapLocation, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
if index > (self.attributedLabel.text?.count)! return
var range : NSRange = NSRange()
if let type = self.attributedLabel.attributedText?.attribute(NSAttributedStringKey(rawValue: "link"), at: index, effectiveRange: &range) as? String
// to get full text which was clicked
print((self.attributedLabel.text! as NSString).substring(with: range))
if type == "termsLink"
//.. do smth
print("termsLink click")
else //policyLink
//.. do smth
print("policyLink click")
【讨论】:
【参考方案3】:您需要使用自定义方案进行普通超链接,例如myapp://function
并在您的应用委托中实现此方法:
optional func application(_ app: UIApplication,
open url: URL,
options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool
guard let scheme = url.scheme, scheme == "myapp" else return
if url.absoluteString.contains("function")
//run code
【讨论】:
以上是关于如何将函数调用(不是超链接)添加到 UILabel 中的 NSAttributedString 的一部分?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Objective-C 将字符添加到 iOS 中的 UILabel 动画?