diff --git a/VDS/BaseClasses/Selector/SelectorItemBase.swift b/VDS/BaseClasses/Selector/SelectorItemBase.swift index 3de2b9db..bc92eb07 100644 --- a/VDS/BaseClasses/Selector/SelectorItemBase.swift +++ b/VDS/BaseClasses/Selector/SelectorItemBase.swift @@ -176,7 +176,7 @@ open class SelectorItemBase: Control, Errorable, /// Executed on initialization for this View. open override func initialSetup() { super.initialSetup() - selectorView.onClick = { [weak self] control in + onClick = { [weak self] control in self?.toggle() } } @@ -247,7 +247,21 @@ open class SelectorItemBase: Control, Errorable, super.accessibilityElements = newValue } } + + /// 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 c95e27a8..090215c2 100644 --- a/VDS/Components/Label/Label.swift +++ b/VDS/Components/Label/Label.swift @@ -371,7 +371,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable { } if let accessibilityElements, !accessibilityElements.isEmpty { - let staticText = UIAccessibilityElement(accessibilityContainer: self) + let staticText = AccessibilityActionElement(accessibilityContainer: self) staticText.accessibilityLabel = text staticText.accessibilityFrameInContainerSpace = bounds @@ -385,12 +385,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? { @@ -422,4 +448,9 @@ open class Label: UILabel, ViewProtocol, UserInfoable { accessibilityElements?.append(element) return element } + + public override func accessibilityActivate() -> Bool { + return false + } + }