1. リンクタップは可能である、その他のテキストは操作無反応とする
2. ダブルタップによるテキスト選択動作は不可である
3. ロングタップは不可である
UITextViewのカスタムViewを作成する
条件1から3まで満たすようなカスタムViewを作ります。この方法は、Stackoverflowに書かれているものを参考にしました。
UITextView: Disable selection, allow links
class UnselectableTextView: UITextView {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
guard let position = closestPosition(to: point) else { return false }
guard let range = tokenizer.rangeEnclosingPosition(
position,
with: .character,
inDirection: UITextDirection(rawValue: UITextLayoutDirection.left.rawValue)
) else { return false }
let startIndex = offset(from: beginningOfDocument, to: range.start)
return attributedText.attribute(.link, at: startIndex, effectiveRange: nil) != nil
}
override func becomeFirstResponder() -> Bool {
return false
}
}
override func point() にて、タップした位置のテキストがリンクであるかどうか判定し、override func becomeFirstResponder() にてダブルタップとロングタップを抑制しています。
ViewControllerに実装するときは、次のようになります。
class ViewController: UIViewController {
@IBOutlet weak var textView: UnselectableTextView!
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
}
private func setupViews() {
textView.delegate = self
textView.isEditable = false
textView.isSelectable = true
textView.backgroundColor = .clear
let attributedString = NSMutableAttributedString(string: "this textview has a link test.")
attributedString.addAttribute(.link, value: "https://www.google.com", range: NSRange(location: 20, length: 4))
textView.attributedText = attributedString
}
}
extension UIViewController: UITextViewDelegate {
public func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
print(URL.absoluteString)
return false
}
}
ロングタップをハンドリングする
上記で作成したUnselectableTextViewに、独自の UILongPressGestureRecognizer を組み込もうとしたが断念。UITextViewの GestureRecognizer とConflictしてしまい、良い感じで実装できずでした。
代替案として、UnselectableTextViewの後ろにUIViewを配置して、このUIViewにてロングタップをハンドリングさせます。
class ViewController: UIViewController {
private func setupGesture() {
let longPressGesture = UILongPressGestureRecognizer(
target: self,
action: #selector(ViewController.longPress(_:))
)
longPressGesture.delegate = self
backgroundView.addGestureRecognizer(longPressGesture)
}
}
extension UIViewController: UIGestureRecognizerDelegate {
@objc func longPress(_ sender: UILongPressGestureRecognizer) {
print(sender.state.rawValue.description)
}
}
0 件のコメント:
コメントを投稿