Swiftで属性付きテキストのタップを検出する
初心者にとっては、セットアップを行う方法を知るのが少し難しい場合があります(とにかくそれは私のためでした)。この例は少し充実しています。
UITextView
プロジェクトにを追加します。
出口
という名前のコンセントでUITextView
をに接続します。ViewController
textView
カスタム属性
Extensionを作成してカスタム属性を作成します。
注:この手順は技術的にオプションですが、行わない場合は、次の部分でコードを編集して、などの標準属性を使用する必要がありますNSAttributedString.Key.foregroundColor
。カスタム属性を使用する利点は、属性付きテキスト範囲に格納する値を定義できることです。
で新しいSwiftファイルを追加する File> New> File ...> iOS> Source> Swift File Swiftファイルます。あなたはそれをあなたが望むものと呼ぶことができます。私はNSAttributedStringKey + CustomAttribute.swiftと呼んでいます。
次のコードを貼り付けます。
import Foundation
extension NSAttributedString.Key {
static let myAttributeName = NSAttributedString.Key(rawValue: "MyCustomAttribute")
}
コード
ViewController.swiftのコードを次のコードに置き換えます。に注意してくださいUIGestureRecognizerDelegate
。
import UIKit
class ViewController: UIViewController, UIGestureRecognizerDelegate {
@IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
// Create an attributed string
let myString = NSMutableAttributedString(string: "Swift attributed text")
// Set an attribute on part of the string
let myRange = NSRange(location: 0, length: 5) // range of "Swift"
let myCustomAttribute = [ NSAttributedString.Key.myAttributeName: "some value"]
myString.addAttributes(myCustomAttribute, range: myRange)
textView.attributedText = myString
// Add tap gesture recognizer to Text View
let tap = UITapGestureRecognizer(target: self, action: #selector(myMethodToHandleTap(_:)))
tap.delegate = self
textView.addGestureRecognizer(tap)
}
@objc func myMethodToHandleTap(_ sender: UITapGestureRecognizer) {
let myTextView = sender.view as! UITextView
let layoutManager = myTextView.layoutManager
// location of tap in myTextView coordinates and taking the inset into account
var location = sender.location(in: myTextView)
location.x -= myTextView.textContainerInset.left;
location.y -= myTextView.textContainerInset.top;
// character index at tap location
let characterIndex = layoutManager.characterIndex(for: location, in: myTextView.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
// if index is valid then do something.
if characterIndex < myTextView.textStorage.length {
// print the character index
print("character index: \(characterIndex)")
// print the character at the index
let myRange = NSRange(location: characterIndex, length: 1)
let substring = (myTextView.attributedText.string as NSString).substring(with: myRange)
print("character at index: \(substring)")
// check if the tap location has a certain attribute
let attributeName = NSAttributedString.Key.myAttributeName
let attributeValue = myTextView.attributedText?.attribute(attributeName, at: characterIndex, effectiveRange: nil)
if let value = attributeValue {
print("You tapped on \(attributeName.rawValue) and the value is: \(value)")
}
}
}
}
「Swift」の「w」をタップすると、次の結果が得られます。
character index: 1
character at index: w
You tapped on MyCustomAttribute and the value is: some value
ノート
- ここではカスタム属性を使用しましたが、同じように簡単にできました
NSAttributedString.Key.foregroundColor
が、の値を持つのは(テキストの色)とでしたUIColor.green
。
- 以前はテキストビューを編集または選択することはできませんでしたが、Swift 4.2に対する私の更新された回答では、これらが選択されているかどうかに関係なく、正常に機能しているようです。
さらなる研究
この回答は、この質問に対する他のいくつかの回答に基づいています。これらに加えて、