Merge branch 'feature/label_accessibility' into 'develop'
Label Accessibility See merge request BPHV_MIPS/mvm_core_ui!96
This commit is contained in:
commit
814d470775
@ -14,7 +14,7 @@ public typealias ActionBlock = () -> ()
|
||||
|
||||
@objcMembers open class Label: UILabel, MVMCoreViewProtocol, MVMCoreUIMoleculeViewProtocol, MVMCoreUIViewConstrainingProtocol, MFButtonProtocol {
|
||||
//------------------------------------------------------
|
||||
// MARK: - General Properties
|
||||
// MARK: - Properties
|
||||
//------------------------------------------------------
|
||||
|
||||
public var makeWholeViewClickable = false
|
||||
@ -56,12 +56,22 @@ public typealias ActionBlock = () -> ()
|
||||
public struct ActionableClause {
|
||||
var range: NSRange?
|
||||
var actionBlock: ActionBlock?
|
||||
var accessibilityID: Int = 0
|
||||
|
||||
func performAction() {
|
||||
actionBlock?()
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Convenience Setter For objective-C
|
||||
//------------------------------------------------------
|
||||
|
||||
/// Sets the clauses array to empty.
|
||||
@objc public func setEmptyClauses() {
|
||||
clauses = []
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Initialization
|
||||
//------------------------------------------------------
|
||||
@ -72,6 +82,8 @@ public typealias ActionBlock = () -> ()
|
||||
numberOfLines = 0
|
||||
lineBreakMode = .byWordWrapping
|
||||
translatesAutoresizingMaskIntoConstraints = false
|
||||
clauses = []
|
||||
accessibilityCustomActions = []
|
||||
|
||||
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(textLinkTapped(_:)))
|
||||
tapGesture.numberOfTapsRequired = 1
|
||||
@ -164,7 +176,7 @@ public typealias ActionBlock = () -> ()
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Functions
|
||||
// MARK: - Style
|
||||
//------------------------------------------------------
|
||||
|
||||
@objc public static func setLabel(_ label: UILabel?, withHTML html: String?) {
|
||||
@ -293,10 +305,9 @@ public typealias ActionBlock = () -> ()
|
||||
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 actionBlock = actionLabel.createActionBlockFrom(actionMap: json, additionalData: additionalData, delegateObject: delegate)
|
||||
actionLabel.appendActionableClause(range: range, actionBlock: actionBlock)
|
||||
|
||||
default:
|
||||
continue
|
||||
}
|
||||
@ -400,7 +411,7 @@ public typealias ActionBlock = () -> ()
|
||||
|
||||
/**
|
||||
Appends an external link image to the end of the attributed string.
|
||||
Will provide one whitespace to the left of the icon
|
||||
Will provide one whitespace to the left of the icon; adds 2 chars to the end of the string.
|
||||
*/
|
||||
@objc public func appendExternalLinkIcon() {
|
||||
|
||||
@ -417,7 +428,7 @@ public typealias ActionBlock = () -> ()
|
||||
Insert external link icon anywhere within text of Label.
|
||||
|
||||
- Note: Each icon insertion adds 1 additional characters to the overall text length.
|
||||
Therefore, you MUST insert icons and links in the order they would appear.
|
||||
Therefore, you **MUST** insert icons and links in the order they would appear.
|
||||
- parameter index: Location within the associated text to insert an external Link Icon
|
||||
*/
|
||||
public func insertExternalLinkIcon(at index: Int) {
|
||||
@ -485,6 +496,12 @@ public typealias ActionBlock = () -> ()
|
||||
|
||||
return containsAttachment
|
||||
}
|
||||
|
||||
func appendActionableClause(range: NSRange, actionBlock: @escaping ActionBlock) {
|
||||
|
||||
let accessibleAction = customAccessibilityAction(range: range)
|
||||
clauses.append(ActionableClause(range: range, actionBlock: actionBlock, accessibilityID: accessibleAction?.hash ?? -1))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Atomization
|
||||
@ -496,6 +513,8 @@ extension Label {
|
||||
textAlignment = .left
|
||||
originalAttributedString = nil
|
||||
styleB2(true)
|
||||
accessibilityCustomActions = []
|
||||
clauses = []
|
||||
}
|
||||
|
||||
@objc public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
|
||||
@ -524,7 +543,7 @@ extension Label {
|
||||
// MARK: - Multi-Action Functionality
|
||||
extension Label {
|
||||
|
||||
/// Reseting to default Label values.
|
||||
/// Applied to existing text. Removes underlines of tappable links and assoated actionable clauses.
|
||||
@objc public func clearActionableClauses() {
|
||||
|
||||
guard let attributedText = attributedText else { return }
|
||||
@ -536,6 +555,7 @@ extension Label {
|
||||
}
|
||||
|
||||
self.attributedText = mutableAttributedString
|
||||
accessibilityElements = []
|
||||
clauses = []
|
||||
}
|
||||
|
||||
@ -572,7 +592,7 @@ extension Label {
|
||||
@objc public func addTappableLinkAttribute(range: NSRange, actionBlock: @escaping ActionBlock) {
|
||||
|
||||
setActionAttributes(range: range)
|
||||
clauses.append(ActionableClause(range: range, actionBlock: actionBlock))
|
||||
appendActionableClause(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -587,10 +607,8 @@ 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 actionBlock = createActionBlockFrom(actionMap: actionMap, additionalData: additionalData, delegateObject: delegateObject)
|
||||
appendActionableClause(range: range, actionBlock: actionBlock)
|
||||
}
|
||||
|
||||
@objc private func textLinkTapped(_ gesture: UITapGestureRecognizer) {
|
||||
@ -642,3 +660,32 @@ extension UITapGestureRecognizer {
|
||||
return NSLocationInRange(indexOfGlyph, targetRange)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Accessibility
|
||||
extension Label {
|
||||
|
||||
func customAccessibilityAction(range: NSRange) -> UIAccessibilityCustomAction? {
|
||||
|
||||
guard let text = text else { return nil }
|
||||
|
||||
if accessibilityHint == nil {
|
||||
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "swipe_to_select_with_action_hint")
|
||||
}
|
||||
|
||||
let actionText = NSString(string: text).substring(with: range)
|
||||
let accessibleAction = UIAccessibilityCustomAction(name: actionText, target: self, selector: #selector(accessibilityCustomAction(_:)))
|
||||
accessibilityCustomActions?.append(accessibleAction)
|
||||
|
||||
return accessibleAction
|
||||
}
|
||||
|
||||
@objc public func accessibilityCustomAction(_ action: UIAccessibilityCustomAction) {
|
||||
|
||||
for clause in clauses {
|
||||
if action.hash == clause.accessibilityID {
|
||||
clause.performAction()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +64,15 @@ 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, accessibilityID: accessibleAction.hash)]
|
||||
label.accessibilityCustomActions = [accessibleAction]
|
||||
|
||||
if label.accessibilityHint == nil {
|
||||
label.accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "swipe_to_select_with_action_hint")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
|
||||
//// Accessibility
|
||||
"AccCloseButton" = "Close";
|
||||
"swipe_to_select_with_action_hint" = "swipe up or down to select action, then double tap to select.";
|
||||
// Tab
|
||||
"AccTab" = ", tab";
|
||||
"AccTabHint" = "Double tap to select.";
|
||||
|
||||
@ -6,6 +6,9 @@
|
||||
Copyright © 2017 myverizon. All rights reserved.
|
||||
*/
|
||||
|
||||
// Accessibility
|
||||
"swipe_to_select_with_action_hint" = "deslízate hacia arriba o hacia abajo para seleccionar la acción, luego toca dos veces para seleccionar.";
|
||||
|
||||
"AccCloseButton" = "Cerrar";
|
||||
// Tab
|
||||
"AccTab" = ", pestaña";
|
||||
|
||||
@ -6,6 +6,9 @@
|
||||
Copyright © 2017 myverizon. All rights reserved.
|
||||
*/
|
||||
|
||||
// Accessibility
|
||||
"swipe_to_select_with_action_hint" = "deslízate hacia arriba o hacia abajo para seleccionar la acción, luego toca dos veces para seleccionar.";
|
||||
|
||||
"AccCloseButton" = "Cerrar";
|
||||
// Tab
|
||||
"AccTab" = ", pestaña";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user