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] = [] {
|
public var clauses: [ActionableClause] = [] {
|
||||||
didSet {
|
didSet { isUserInteractionEnabled = !clauses.isEmpty }
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used for tappable links in the text.
|
/// Used for tappable links in the text.
|
||||||
public struct ActionableClause {
|
public struct ActionableClause {
|
||||||
var range: NSRange?
|
var range: NSRange?
|
||||||
var actionBlock: ActionBlock?
|
var actionBlock: ActionBlock?
|
||||||
|
var text: String?
|
||||||
|
var hash: Int = 0
|
||||||
|
|
||||||
func performAction() {
|
func performAction() {
|
||||||
actionBlock?()
|
actionBlock?()
|
||||||
@ -72,8 +65,7 @@ public typealias ActionBlock = () -> Void
|
|||||||
numberOfLines = 0
|
numberOfLines = 0
|
||||||
lineBreakMode = .byWordWrapping
|
lineBreakMode = .byWordWrapping
|
||||||
translatesAutoresizingMaskIntoConstraints = false
|
translatesAutoresizingMaskIntoConstraints = false
|
||||||
isAccessibilityElement = false
|
accessibilityCustomActions = []
|
||||||
accessibilityElements = []
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc public init() {
|
@objc public init() {
|
||||||
@ -267,10 +259,14 @@ public typealias ActionBlock = () -> Void
|
|||||||
guard let actionLabel = label as? Label else { continue }
|
guard let actionLabel = label as? Label else { continue }
|
||||||
|
|
||||||
actionLabel.addActionAttributes(range: range, string: attributedString)
|
actionLabel.addActionAttributes(range: range, string: attributedString)
|
||||||
actionLabel.clauses.append(ActionableClause(range: range,
|
let accessibleAction = actionLabel.customAccessibilityAction(range: range)
|
||||||
actionBlock: actionLabel.createActionBlockFrom(actionMap: json,
|
let actionBlock = actionLabel.createActionBlockFrom(actionMap: json, additionalData: additionalData, delegateObject: delegate)
|
||||||
additionalData: additionalData,
|
let actionableClause = ActionableClause(range: range,
|
||||||
delegateObject: delegate)))
|
actionBlock: actionBlock,
|
||||||
|
text: accessibleAction?.name ?? "",
|
||||||
|
hash: accessibleAction?.hash ?? -1)
|
||||||
|
actionLabel.clauses.append(actionableClause)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -416,7 +412,7 @@ extension Label {
|
|||||||
originalAttributedString = nil
|
originalAttributedString = nil
|
||||||
hasAttachmentImage = false
|
hasAttachmentImage = false
|
||||||
styleB2(true)
|
styleB2(true)
|
||||||
accessibilityElements = []
|
accessibilityCustomActions = []
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
@objc public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||||
@ -457,7 +453,7 @@ extension Label {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.attributedText = mutableAttributedString
|
self.attributedText = mutableAttributedString
|
||||||
// accessibleClauses = []
|
accessibilityElements = []
|
||||||
clauses = []
|
clauses = []
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,7 +491,9 @@ extension Label {
|
|||||||
@objc public func addTappableLinkAttribute(range: NSRange, actionBlock: @escaping ActionBlock) {
|
@objc public func addTappableLinkAttribute(range: NSRange, actionBlock: @escaping ActionBlock) {
|
||||||
|
|
||||||
setActionAttributes(range: range)
|
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?) {
|
@objc public func addTappableLinkAttribute(range: NSRange, actionMap: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?, delegateObject: DelegateObject?) {
|
||||||
|
|
||||||
setActionAttributes(range: range)
|
setActionAttributes(range: range)
|
||||||
clauses.append(ActionableClause(range: range,
|
let actionText = NSString(string: text!).substring(with: range)
|
||||||
actionBlock: createActionBlockFrom(actionMap: actionMap,
|
let accessibleAction = customAccessibilityAction(range: range)
|
||||||
additionalData: additionalData,
|
let actionBlock = createActionBlockFrom(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||||
delegateObject: delegateObject)))
|
clauses.append(ActionableClause(range: range, actionBlock: actionBlock, text: actionText, hash: accessibleAction!.hash))
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func textLinkTapped(_ gesture: UITapGestureRecognizer) {
|
@objc private func textLinkTapped(_ gesture: UITapGestureRecognizer) {
|
||||||
@ -574,66 +572,28 @@ extension UITapGestureRecognizer {
|
|||||||
// MARK: - Accessibility
|
// MARK: - Accessibility
|
||||||
extension Label {
|
extension Label {
|
||||||
|
|
||||||
override open func accessibilityActivate() -> Bool {
|
func customAccessibilityAction(range: NSRange) -> UIAccessibilityCustomAction? {
|
||||||
// let point = accessibilityActivationPoint
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
open override func accessibilityElementDidBecomeFocused() {
|
|
||||||
|
|
||||||
}
|
guard let text = text else { return nil }
|
||||||
|
|
||||||
open override func accessibilityElementCount() -> Int {
|
if accessibilityHint == nil {
|
||||||
return accessibilityElements?.count ?? 0
|
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "plan_selector_int_swipe_action_hint")
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
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 }
|
for clause in clauses {
|
||||||
|
if action.hash == clause.hash {
|
||||||
let textStorage = NSTextStorage(attributedString: attributedText)
|
clause.performAction()
|
||||||
let layoutManager = NSLayoutManager()
|
return
|
||||||
|
}
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,7 +64,11 @@ public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProt
|
|||||||
if newActionBlock == nil {
|
if newActionBlock == nil {
|
||||||
label?.clearActionableClauses()
|
label?.clearActionableClauses()
|
||||||
} else {
|
} 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
|
//// Accessibility
|
||||||
"AccCloseButton" = "Close";
|
"AccCloseButton" = "Close";
|
||||||
|
"plan_selector_int_swipe_action_hint" = "swipe up or down to select action, then double tap to select.";
|
||||||
// Tab
|
// Tab
|
||||||
"AccTab" = ", tab";
|
"AccTab" = ", tab";
|
||||||
"AccTabHint" = "Double tap to select.";
|
"AccTabHint" = "Double tap to select.";
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user