From bdd481109afb40bb231f71bfcdb586fbab49163e Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 19 Jun 2024 10:58:48 -0500 Subject: [PATCH] allow touch events for labels to bleed through Signed-off-by: Matt Bruce --- .../Selector/SelectorItemBase.swift | 14 ++++++++++ VDS/Components/Label/Label.swift | 28 ++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/VDS/BaseClasses/Selector/SelectorItemBase.swift b/VDS/BaseClasses/Selector/SelectorItemBase.swift index fd3f6f2b..35c77922 100644 --- a/VDS/BaseClasses/Selector/SelectorItemBase.swift +++ b/VDS/BaseClasses/Selector/SelectorItemBase.swift @@ -198,7 +198,21 @@ open class SelectorItemBase: Control, Errorable, setAccessibilityLabel(for: [selectorView, label, childLabel, errorLabel]) accessibilityValue = accessibilityValueText } + + /// Overriden to take the hit if there is an onClickSubscriber and the view is not a UIControl + open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + let labelPoint = convert(point, to: label) + let childLabelPoint = convert(point, to: childLabel) + if label.isAction(for: labelPoint) { + return label + } else if childLabel.isAction(for: childLabelPoint) { + return childLabel + } else { + return super.hitTest(point, with: event) + } + } + /// Resets to default settings. open override func reset() { super.reset() diff --git a/VDS/Components/Label/Label.swift b/VDS/Components/Label/Label.swift index c094f775..9dd9bf1d 100644 --- a/VDS/Components/Label/Label.swift +++ b/VDS/Components/Label/Label.swift @@ -383,12 +383,38 @@ open class Label: UILabel, ViewProtocol, UserInfoable { @objc private func textLinkTapped(_ gesture: UITapGestureRecognizer) { for actionable in actions { // This determines if we tapped on the desired range of text. - if gesture.didTapActionInLabel(self, inRange: actionable.range) { + let location = gesture.location(in: self) + if didTapActionInLabel(location, inRange: actionable.range) { actionable.performAction() return } } } + + public func isAction(for location: CGPoint) -> Bool { + for actionable in actions { + if didTapActionInLabel(location, inRange: actionable.range) { + return true + } + } + return false + } + + private func didTapActionInLabel(_ location: CGPoint, inRange targetRange: NSRange) -> Bool { + + guard let attributedText else { return false } + let layoutManager = NSLayoutManager() + let textContainer = NSTextContainer(size: bounds.size) + let textStorage = NSTextStorage(attributedString: attributedText) + layoutManager.addTextContainer(textContainer) + textStorage.addLayoutManager(layoutManager) + + let characterIndex = layoutManager.characterIndex(for: location, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil) + + guard let _ = attributedText.attribute(NSAttributedString.Key.action, at: characterIndex, effectiveRange: nil) as? String, characterIndex < attributedText.length else { return false } + return true + } + private func customAccessibilityElement(text: String?, range: NSRange, accessibleText: String? = nil) -> AccessibilityActionElement? {