Accessibility update for Label and LabelWithInternalButton.
This commit is contained in:
parent
244e3c0df3
commit
6775467606
@ -40,22 +40,15 @@ public typealias ActionBlock = () -> Void
|
||||
//------------------------------------------------------
|
||||
|
||||
public var clauses: [ActionableClause] = [] {
|
||||
didSet {
|
||||
isUserInteractionEnabled = !clauses.isEmpty
|
||||
|
||||
// Accessibility
|
||||
let element = UIAccessibilityElement(accessibilityContainer: self)
|
||||
element.accessibilityFrameInContainerSpace = convert(boundingRect(forCharacterRange: clauses.last!.range!), to: nil) //CGRect(x: 10, y: 10, width: 100, height: 30)
|
||||
element.accessibilityLabel = "Testing"
|
||||
element.accessibilityTraits = .button
|
||||
accessibilityElements?.append(element)
|
||||
}
|
||||
didSet { isUserInteractionEnabled = !clauses.isEmpty }
|
||||
}
|
||||
|
||||
/// Used for tappable links in the text.
|
||||
public struct ActionableClause {
|
||||
var range: NSRange?
|
||||
var actionBlock: ActionBlock?
|
||||
var text: String?
|
||||
var hash: Int = 0
|
||||
|
||||
func performAction() {
|
||||
actionBlock?()
|
||||
@ -72,8 +65,7 @@ public typealias ActionBlock = () -> Void
|
||||
numberOfLines = 0
|
||||
lineBreakMode = .byWordWrapping
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
isAccessibilityElement = false
|
||||
accessibilityElements = []
|
||||
accessibilityCustomActions = []
|
||||
}
|
||||
|
||||
@objc public init() {
|
||||
@ -267,10 +259,14 @@ public typealias ActionBlock = () -> Void
|
||||
guard let actionLabel = label as? Label else { continue }
|
||||
|
||||
actionLabel.addActionAttributes(range: range, string: attributedString)
|
||||
actionLabel.clauses.append(ActionableClause(range: range,
|
||||
actionBlock: actionLabel.createActionBlockFrom(actionMap: json,
|
||||
additionalData: additionalData,
|
||||
delegateObject: delegate)))
|
||||
let accessibleAction = actionLabel.customAccessibilityAction(range: range)
|
||||
let actionBlock = actionLabel.createActionBlockFrom(actionMap: json, additionalData: additionalData, delegateObject: delegate)
|
||||
let actionableClause = ActionableClause(range: range,
|
||||
actionBlock: actionBlock,
|
||||
text: accessibleAction?.name ?? "",
|
||||
hash: accessibleAction?.hash ?? -1)
|
||||
actionLabel.clauses.append(actionableClause)
|
||||
|
||||
default:
|
||||
continue
|
||||
}
|
||||
@ -416,7 +412,7 @@ extension Label {
|
||||
originalAttributedString = nil
|
||||
hasAttachmentImage = false
|
||||
styleB2(true)
|
||||
accessibilityElements = []
|
||||
accessibilityCustomActions = []
|
||||
}
|
||||
|
||||
@objc public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
@ -457,7 +453,7 @@ extension Label {
|
||||
}
|
||||
|
||||
self.attributedText = mutableAttributedString
|
||||
// accessibleClauses = []
|
||||
accessibilityElements = []
|
||||
clauses = []
|
||||
}
|
||||
|
||||
@ -495,7 +491,9 @@ extension Label {
|
||||
@objc public func addTappableLinkAttribute(range: NSRange, actionBlock: @escaping ActionBlock) {
|
||||
|
||||
setActionAttributes(range: range)
|
||||
clauses.append(ActionableClause(range: range, actionBlock: actionBlock))
|
||||
let actionText = NSString(string: text!).substring(with: range)
|
||||
let accessibleAction = customAccessibilityAction(range: range)
|
||||
clauses.append(ActionableClause(range: range, actionBlock: actionBlock, text: actionText, hash: accessibleAction!.hash))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -511,10 +509,10 @@ extension Label {
|
||||
@objc public func addTappableLinkAttribute(range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||
|
||||
setActionAttributes(range: range)
|
||||
clauses.append(ActionableClause(range: range,
|
||||
actionBlock: createActionBlockFrom(actionMap: actionMap,
|
||||
additionalData: additionalData,
|
||||
delegateObject: delegateObject)))
|
||||
let actionText = NSString(string: text!).substring(with: range)
|
||||
let accessibleAction = customAccessibilityAction(range: range)
|
||||
let actionBlock = createActionBlockFrom(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
clauses.append(ActionableClause(range: range, actionBlock: actionBlock, text: actionText, hash: accessibleAction!.hash))
|
||||
}
|
||||
|
||||
@objc private func textLinkTapped(_ gesture: UITapGestureRecognizer) {
|
||||
@ -574,66 +572,28 @@ extension UITapGestureRecognizer {
|
||||
// MARK: - Accessibility
|
||||
extension Label {
|
||||
|
||||
override open func accessibilityActivate() -> Bool {
|
||||
// let point = accessibilityActivationPoint
|
||||
return true
|
||||
}
|
||||
|
||||
open override func accessibilityElementDidBecomeFocused() {
|
||||
func customAccessibilityAction(range: NSRange) -> UIAccessibilityCustomAction? {
|
||||
|
||||
}
|
||||
|
||||
open override func accessibilityElementCount() -> Int {
|
||||
return accessibilityElements?.count ?? 0
|
||||
}
|
||||
|
||||
open override func accessibilityElement(at index: Int) -> Any? {
|
||||
return accessibilityElements?[index]
|
||||
}
|
||||
|
||||
open override func index(ofAccessibilityElement element: Any) -> Int {
|
||||
return 0//accessibilityElements?.firstIndex(of: element as! UIAccessibilityElement)!
|
||||
}
|
||||
|
||||
/*
|
||||
var accessibleClauses: [UIAccessibilityElement] {
|
||||
|
||||
var elements = [UIAccessibilityElement]()
|
||||
for clause in clauses {
|
||||
let element = UIAccessibilityElement(accessibilityContainer: self)
|
||||
// let rect = CGRect(x: 10, y: 10, width: 100, height: 30)
|
||||
element.accessibilityFrame = convert(self.frame, to: nil)
|
||||
// element.accessibilityFrame = convert(conceptualSize(range: clause.range)!, to: nil)
|
||||
// element.accessibilityFrameInContainerSpace = rect
|
||||
element.accessibilityLabel = "Testing"
|
||||
element.accessibilityTraits = .button
|
||||
element.isAccessibilityElement = true
|
||||
elements.append(element)
|
||||
guard let text = text else { return nil }
|
||||
|
||||
if accessibilityHint == nil {
|
||||
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "plan_selector_int_swipe_action_hint")
|
||||
}
|
||||
accessibilityElements = elements
|
||||
return elements
|
||||
|
||||
let actionText = NSString(string: text).substring(with: range)
|
||||
let accessibleAction = UIAccessibilityCustomAction(name: actionText, target: self, selector: #selector(accessibilityCustomAction(_:)))
|
||||
accessibilityCustomActions?.append(accessibleAction)
|
||||
|
||||
return accessibleAction
|
||||
}
|
||||
*/
|
||||
|
||||
func boundingRect(forCharacterRange range: NSRange) -> CGRect? {
|
||||
@objc public func accessibilityCustomAction(_ action: UIAccessibilityCustomAction) {
|
||||
|
||||
guard let attributedText = attributedText else { return nil }
|
||||
|
||||
let textStorage = NSTextStorage(attributedString: attributedText)
|
||||
let layoutManager = NSLayoutManager()
|
||||
|
||||
textStorage.addLayoutManager(layoutManager)
|
||||
|
||||
let textContainer = NSTextContainer(size: bounds.size)
|
||||
textContainer.lineFragmentPadding = 0.0
|
||||
|
||||
layoutManager.addTextContainer(textContainer)
|
||||
|
||||
var glyphRange = NSRange()
|
||||
|
||||
// Convert the range for glyphs.
|
||||
layoutManager.characterRange(forGlyphRange: range, actualGlyphRange: &glyphRange)
|
||||
|
||||
return layoutManager.boundingRect(forGlyphRange: glyphRange, in: textContainer)
|
||||
for clause in clauses {
|
||||
if action.hash == clause.hash {
|
||||
clause.performAction()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +64,11 @@ public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProt
|
||||
if newActionBlock == nil {
|
||||
label?.clearActionableClauses()
|
||||
} else {
|
||||
label?.clauses = [Label.ActionableClause(range: actionRange, actionBlock: newActionBlock)]
|
||||
guard let label = label else { return }
|
||||
|
||||
let accessibleAction = UIAccessibilityCustomAction(name: actionText ?? "", target: label, selector: #selector(label.accessibilityCustomAction(_:)))
|
||||
label.clauses = [Label.ActionableClause(range: actionRange, actionBlock: newActionBlock, text: actionText ?? "", hash: accessibleAction.hash)]
|
||||
label.accessibilityCustomActions = [accessibleAction]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
|
||||
//// Accessibility
|
||||
"AccCloseButton" = "Close";
|
||||
"plan_selector_int_swipe_action_hint" = "swipe up or down to select action, then double tap to select.";
|
||||
// Tab
|
||||
"AccTab" = ", tab";
|
||||
"AccTabHint" = "Double tap to select.";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user