リファレンスソース -
Create tap-able "links" in the NSAttributedString of a UILabel?
それは、迅速3.0
に変換され、これを試してみてください -
以下のようなUILabelのためのサブクラスを作成します -
スウィフト3.0
01ビューコントローラのご
viewDidLoad
メソッド内
class CustomLabel: UILabel {
let layoutManager = NSLayoutManager()
let textContainer = NSTextContainer(size: CGSize.zero)
var textStorage = NSTextStorage() {
didSet {
textStorage.addLayoutManager(layoutManager)
}
}
var onCharacterTapped: ((_ label: UILabel, _ characterIndex: Int) -> Void)?
let tapGesture = UITapGestureRecognizer()
override var attributedText: NSAttributedString? {
didSet {
if let attributedText = attributedText {
textStorage = NSTextStorage(attributedString: attributedText)
} else {
textStorage = NSTextStorage()
}
}
}
override var lineBreakMode: NSLineBreakMode {
didSet {
textContainer.lineBreakMode = lineBreakMode
}
}
override var numberOfLines: Int {
didSet {
textContainer.maximumNumberOfLines = numberOfLines
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUp()
}
override init(frame: CGRect) {
super.init(frame: frame)
setUp()
}
func setUp() {
isUserInteractionEnabled = true
layoutManager.addTextContainer(textContainer)
textContainer.lineFragmentPadding = 0
textContainer.lineBreakMode = lineBreakMode
textContainer.maximumNumberOfLines = numberOfLines
tapGesture.addTarget(self, action: #selector(CustomLabel.labelTapped(_:)))
addGestureRecognizer(tapGesture)
}
override func layoutSubviews() {
super.layoutSubviews()
textContainer.size = bounds.size
}
func labelTapped(_ gesture: UITapGestureRecognizer) {
guard gesture.state == .ended else {
return
}
let locationOfTouch = gesture.location(in: gesture.view)
let textBoundingBox = layoutManager.usedRect(for: textContainer)
let textContainerOffset = CGPoint(x: (bounds.width - textBoundingBox.width)/2 - textBoundingBox.minX,
y: (bounds.height - textBoundingBox.height)/2 - textBoundingBox.minY)
let locationOfTouchInTextContainer = CGPoint(x: locationOfTouch.x - textContainerOffset.x, y: locationOfTouch.y - textContainerOffset.y)
let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer,
in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
onCharacterTapped?(self, indexOfCharacter)
}
}
以下のようにそのクラスのインスタンスを作成します - あなたはの範囲を知っているあなたのviewDidLoad()内のリンクを追加している
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let label = CustomLabel()
label.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(label)
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[view]-|",
options: [], metrics: nil, views: ["view" : label]))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[view]-|",
options: [], metrics: nil, views: ["view" : label]))
let attributedString = NSMutableAttributedString(string: "String with a link", attributes: nil)
let linkRange = NSMakeRange(14, 4); // for the word "link" in the string above
let linkAttributes: [String : AnyObject] = [
NSForegroundColorAttributeName : UIColor.blue, NSUnderlineStyleAttributeName : NSUnderlineStyle.styleSingle.rawValue as AnyObject,
NSLinkAttributeName: "http://www.apple.com" as AnyObject]
attributedString.setAttributes(linkAttributes, range:linkRange)
label.attributedText = attributedString
label.onCharacterTapped = { label, characterIndex in
// DO YOUR STUFF HERE
}
}
をする(14、4) 。私の場合、私はリンクの範囲を知らない。それが私が決定したいことです。 – alionthego
私の知る限り、UILableを使用してこれを実現したい場合は、範囲を知っている必要があります。そうでない場合は、UITextViewを使用する必要があります。 –
UITextViewはパフォーマンス上の理由からオプションではありません。 – alionthego