update label for accessibility elements
Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
parent
53c2a63dbb
commit
304416afdb
@ -95,7 +95,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
|
||||
.sink { [weak self] notification in
|
||||
self?.setNeedsUpdate()
|
||||
}.store(in: &subscribers)
|
||||
|
||||
|
||||
backgroundColor = .clear
|
||||
numberOfLines = 0
|
||||
lineBreakMode = .byWordWrapping
|
||||
@ -106,7 +106,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
|
||||
setNeedsUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
open func setup() {}
|
||||
|
||||
/// Resets to default settings.
|
||||
@ -156,6 +156,9 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
|
||||
|
||||
//force a drawText
|
||||
setNeedsDisplay()
|
||||
|
||||
setNeedsLayout()
|
||||
layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,7 +177,25 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
|
||||
|
||||
//add attribute on the string
|
||||
attribute.setAttribute(on: mutableAttributedString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
applyActions()
|
||||
}
|
||||
|
||||
private func applyActions() {
|
||||
actions = []
|
||||
guard let attributedText else { return }
|
||||
|
||||
let mutableAttributedString = NSMutableAttributedString(attributedString: attributedText)
|
||||
|
||||
if let attributes = attributes {
|
||||
//loop through the models attributes
|
||||
for attribute in attributes {
|
||||
|
||||
//see if the attribute is Actionable
|
||||
if let actionable = attribute as? any ActionLabelAttributeModel{
|
||||
//create a accessibleAction
|
||||
@ -184,9 +205,20 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
|
||||
actions.append(LabelAction(range: actionable.range, action: actionable.action, accessibilityID: customAccessibilityAction?.hashValue ?? -1))
|
||||
}
|
||||
}
|
||||
|
||||
if let accessibilityElements, !accessibilityElements.isEmpty {
|
||||
let staticText = UIAccessibilityElement(accessibilityContainer: self)
|
||||
staticText.accessibilityLabel = text
|
||||
staticText.accessibilityTraits = .staticText
|
||||
staticText.accessibilityFrameInContainerSpace = bounds
|
||||
|
||||
isAccessibilityElement = false
|
||||
self.accessibilityElements = accessibilityElements.compactMap{$0 as? UIAccessibilityElement}.filter { $0.accessibilityLabel != text }
|
||||
self.accessibilityElements?.insert(staticText, at: 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Actionable
|
||||
//--------------------------------------------------
|
||||
@ -218,10 +250,10 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
|
||||
|
||||
private var actions: [LabelAction] = [] {
|
||||
didSet {
|
||||
isUserInteractionEnabled = !actions.isEmpty
|
||||
accessibilityTraits = !actions.isEmpty ? .link : .staticText
|
||||
if actions.isEmpty {
|
||||
tapGesture = nil
|
||||
isUserInteractionEnabled = true
|
||||
accessibilityTraits = .staticText
|
||||
} else {
|
||||
//add tap gesture
|
||||
if tapGesture == nil {
|
||||
@ -253,18 +285,42 @@ open class Label: UILabel, ViewProtocol, UserInfoable {
|
||||
//--------------------------------------------------
|
||||
private func customAccessibilityAction(text: String?, range: NSRange, accessibleText: String? = nil) -> UIAccessibilityCustomAction? {
|
||||
|
||||
guard let text = text else { return nil }
|
||||
//TODO: accessibilityHint for Label
|
||||
// if accessibilityHint == nil {
|
||||
// accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "swipe_to_select_with_action_hint")
|
||||
// }
|
||||
guard let text = text, let attributedText else { return nil }
|
||||
|
||||
let actionText = accessibleText ?? NSString(string:text).substring(with: range)
|
||||
|
||||
// Calculate the frame of the substring
|
||||
let layoutManager = NSLayoutManager()
|
||||
let textContainer = NSTextContainer(size: bounds.size)
|
||||
let textStorage = NSTextStorage(attributedString: attributedText)
|
||||
layoutManager.addTextContainer(textContainer)
|
||||
textStorage.addLayoutManager(layoutManager)
|
||||
|
||||
var glyphRange = NSRange()
|
||||
|
||||
// Convert the range for the substring into a range of glyphs
|
||||
layoutManager.characterRange(forGlyphRange: range, actualGlyphRange: &glyphRange)
|
||||
|
||||
let substringBounds = layoutManager.boundingRect(forGlyphRange: glyphRange, in: textContainer)
|
||||
|
||||
// Create custom accessibility element
|
||||
let element = UIAccessibilityElement(accessibilityContainer: self)
|
||||
element.accessibilityLabel = actionText
|
||||
element.accessibilityTraits = .link
|
||||
element.accessibilityFrameInContainerSpace = substringBounds
|
||||
//TODO: accessibilityHint for Label
|
||||
// element.accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "swipe_to_select_with_action_hint")
|
||||
|
||||
accessibilityElements = (accessibilityElements ?? []).compactMap{$0 as? UIAccessibilityElement}.filter { $0.accessibilityLabel != actionText }
|
||||
accessibilityElements?.append(element)
|
||||
|
||||
let accessibleAction = UIAccessibilityCustomAction(name: actionText, target: self, selector: #selector(accessibilityCustomAction(_:)))
|
||||
accessibilityCustomActions?.append(accessibleAction)
|
||||
return accessibleAction
|
||||
}
|
||||
|
||||
|
||||
|
||||
@objc public func accessibilityCustomAction(_ action: UIAccessibilityCustomAction) {
|
||||
|
||||
for actionable in actions {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user