accessibility fix

This commit is contained in:
Pfeil, Scott Robert 2020-07-06 15:33:25 -04:00
parent 400b43b7ad
commit 63c793fe25
13 changed files with 124 additions and 17 deletions

View File

@ -25,12 +25,9 @@ import UIKit
if numberOfDigits > 0 {
var digitBoxes = [DigitBox]()
let ordinalFormatter = NumberFormatter()
ordinalFormatter.numberStyle = .ordinal
for i in 0..<numberOfDigits {
let newDigitBox = createDigitField()
let accessibileLabel = ordinalFormatter.string(from: NSNumber(value: i + 1)) ?? ""
let accessibileLabel = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: i + 1)) ?? ""
newDigitBox.digitField.accessibilityLabel = "\(accessibileLabel) field of \(numberOfDigits) digit fields"
digitBoxes.append(newDigitBox)
}

View File

@ -26,6 +26,18 @@ open class RadioBox: Control {
return model as? RadioBoxModel
}
public override var isSelected: Bool {
didSet {
updateAccessibility()
}
}
public override var isEnabled: Bool {
didSet {
updateAccessibility()
}
}
// MARK: - MVMCoreViewProtocol
open override func updateView(_ size: CGFloat) {
@ -56,6 +68,8 @@ open class RadioBox: Control {
subTextLabelHeightConstraint?.isActive = true
addTarget(self, action: #selector(selectBox), for: .touchUpInside)
isAccessibilityElement = true
}
// MARK: - MoleculeViewProtocol
@ -63,8 +77,6 @@ open class RadioBox: Control {
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? RadioBoxModel else { return }
isSelected = model.selected
isEnabled = model.enabled
label.text = model.text
subTextLabel.text = model.subText
isOutOfStock = model.strikethrough
@ -72,6 +84,8 @@ open class RadioBox: Control {
if let color = model.selectedAccentColor?.uiColor {
accentColor = color
}
isSelected = model.selected
isEnabled = model.enabled
}
open override func reset() {
@ -91,7 +105,6 @@ open class RadioBox: Control {
strikeLayer = line
}
// Draw the border
borderLayer?.removeFromSuperlayer()
if isSelected {
@ -191,5 +204,25 @@ open class RadioBox: Control {
mask.frame = bounds
return mask
}
// MARK: - Accessibility
public func updateAccessibility() {
var message = ""
if let labelText = label.text, label.hasText {
message += labelText + ", "
}
if let subLabelText = subTextLabel.text, subTextLabel.hasText {
message += subLabelText + ", "
}
accessibilityLabel = message
accessibilityTraits = .button
if isSelected {
accessibilityTraits.insert(.selected)
}
if !isEnabled {
accessibilityTraits.insert(.notEnabled)
}
}
}

View File

@ -17,6 +17,7 @@ open class RadioBoxCollectionViewCell: CollectionViewCell {
open override func setupView() {
super.setupView()
isAccessibilityElement = true
addMolecule(radioBox)
MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0)
}
@ -24,5 +25,12 @@ open class RadioBoxCollectionViewCell: CollectionViewCell {
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? RadioBoxModel else { return }
radioBox.set(with: model, delegateObject, additionalData)
updateAccessibility()
}
open func updateAccessibility() {
accessibilityLabel = radioBox.accessibilityLabel
accessibilityHint = radioBox.accessibilityHint
accessibilityTraits = radioBox.accessibilityTraits
}
}

View File

@ -35,6 +35,13 @@ open class RadioBoxes: View {
}
}
open func updateAccessibilityValue(collectionView: UICollectionView, cell: RadioBoxCollectionViewCell, indexPath: IndexPath) {
guard let format = MVMCoreUIUtility.hardcodedString(withKey: "index_string_of_total"),
let indexString = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: indexPath.row + 1)) else { return }
let total = self.collectionView(collectionView, numberOfItemsInSection: indexPath.section)
cell.accessibilityValue = String(format: format, indexString, total)
}
// MARK: - MVMCoreViewProtocol
open override func setupView() {
super.setupView()
@ -136,6 +143,7 @@ extension RadioBoxes: UICollectionViewDataSource {
if molecule.selected {
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically)
}
updateAccessibilityValue(collectionView: collectionView, cell: cell, indexPath: indexPath)
cell.layoutIfNeeded()
return cell
}
@ -151,11 +159,13 @@ extension RadioBoxes: UICollectionViewDelegate {
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioBoxCollectionViewCell else { return }
cell.radioBox.selectBox()
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
cell.updateAccessibility()
}
open func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioBoxCollectionViewCell else { return }
cell.radioBox.deselectBox()
cell.updateAccessibility()
}
}

View File

@ -24,6 +24,18 @@ open class RadioSwatch: Control {
return model as? RadioSwatchModel
}
public override var isSelected: Bool {
didSet {
updateAccessibility()
}
}
public override var isEnabled: Bool {
didSet {
updateAccessibility()
}
}
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
@ -45,9 +57,9 @@ open class RadioSwatch: Control {
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData)
guard let model = model as? RadioSwatchModel else { return }
bottomText.text = model.text
isSelected = model.selected
isEnabled = model.enabled
bottomText.text = model.text
}
public override func reset() {
@ -163,4 +175,17 @@ open class RadioSwatch: Control {
mask.frame = bounds
return mask
}
// MARK: - Accessibility
public func updateAccessibility() {
accessibilityLabel = bottomText.accessibilityLabel ?? bottomText.text
accessibilityTraits = .button
if isSelected {
accessibilityTraits.insert(.selected)
}
if !isEnabled {
accessibilityTraits.insert(.notEnabled)
}
}
}

View File

@ -12,6 +12,7 @@ open class RadioSwatchCollectionViewCell: CollectionViewCell {
open override func setupView() {
super.setupView()
isAccessibilityElement = true
addMolecule(radioSwatch)
MVMCoreUIUtility.setMarginsFor(contentView, leading: 0, top: 0, trailing: 0, bottom: 0)
}
@ -19,5 +20,24 @@ open class RadioSwatchCollectionViewCell: CollectionViewCell {
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? RadioSwatchModel else { return }
radioSwatch.set(with: model, delegateObject, additionalData)
updateAccessibility()
}
open func updateAccessibility() {
accessibilityLabel = radioSwatch.accessibilityLabel
accessibilityHint = radioSwatch.accessibilityHint
accessibilityTraits = radioSwatch.accessibilityTraits
}
open override func accessibilityElementDidBecomeFocused() {
super.accessibilityElementDidBecomeFocused()
radioSwatch.bottomText.isHidden = false
}
open override func accessibilityElementDidLoseFocus() {
super.accessibilityElementDidLoseFocus()
if !radioSwatch.isSelected {
radioSwatch.bottomText.isHidden = true
}
}
}

View File

@ -101,6 +101,13 @@ open class RadioSwatches: View {
}
collectionViewHeight?.constant = CGFloat(height)
}
open func updateAccessibilityValue(collectionView: UICollectionView, cell: RadioSwatchCollectionViewCell, indexPath: IndexPath) {
guard let format = MVMCoreUIUtility.hardcodedString(withKey: "index_string_of_total"),
let indexString = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: indexPath.row + 1)) else { return }
let total = self.collectionView(collectionView, numberOfItemsInSection: indexPath.section)
cell.accessibilityValue = String(format: format, indexString, total)
}
}
//------------------------------------------------------
@ -128,6 +135,7 @@ extension RadioSwatches: UICollectionViewDataSource {
if molecule.selected {
collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically)
}
updateAccessibilityValue(collectionView: collectionView, cell: cell, indexPath: indexPath)
cell.layoutIfNeeded()
return cell
}
@ -143,10 +151,12 @@ extension RadioSwatches: UICollectionViewDelegate {
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchCollectionViewCell else { return }
cell.radioSwatch.selectSwatch()
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
cell.updateAccessibility()
}
open func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioSwatchCollectionViewCell else { return }
cell.radioSwatch.deselectSwatch()
cell.updateAccessibility()
}
}

View File

@ -110,13 +110,10 @@ open class BarsIndicatorView: CarouselIndicator {
var bars = [(View, NSLayoutConstraint)]()
let ordinalFormatter = NumberFormatter()
ordinalFormatter.numberStyle = .ordinal
for i in 0..<numberOfPages {
let bar = View()
bar.isAccessibilityElement = true
if let accessibleValueFormat = accessibilityValueFormat, let accessibleIndex = ordinalFormatter.string(from: NSNumber(value: i + 1)) {
if let accessibleValueFormat = accessibilityValueFormat, let accessibleIndex = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: i + 1)) {
bar.accessibilityLabel = String(format: accessibleValueFormat, accessibleIndex, numberOfPages)
}
bar.accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccTabHint")

View File

@ -225,11 +225,8 @@ open class CarouselIndicator: Control, CarouselPageControlProtocol {
func formatAccessibilityValue(index: Int, total: Int) {
let ordinalFormatter = NumberFormatter()
ordinalFormatter.numberStyle = .ordinal
guard let accessibleFormat = accessibilityValueFormat,
let accessibleIndex = ordinalFormatter.string(from: NSNumber(value: index))
let accessibleIndex = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: index))
else { return }
accessibilityValue = String(format: accessibleFormat, accessibleIndex, total)

View File

@ -10,6 +10,7 @@
"AccCloseButton" = "Close";
"swipe_to_select_with_action_hint" = "swipe up or down to select action, then double tap to select.";
"AccDisabled" = "Disabled";
"index_string_of_total" = "%@ of %d";
// MARK: Tab
"AccTab" = ", tab";
@ -59,7 +60,6 @@
"radio_not_selected_state" = "Not Selected";
"radio_desc_state" = "Option";
// MARK: Switch / Toggle
"mfswitch_buttonlabel" = "Switch Button";
"Toggle_buttonlabel" = "Toggle Button";

View File

@ -9,6 +9,7 @@
// 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.";
"AccDisabled" = "desactivado";
"index_string_of_total" = "%@ de %d";
"AccCloseButton" = "Cerrar";
// Tab

View File

@ -46,6 +46,9 @@ NS_ASSUME_NONNULL_BEGIN
// Removes any format.
+ (nullable NSString *)removeMdnFormat:(nullable NSString *)mdn;
/// Returns an ordinal formatted string for a number.
+ (nullable NSString *)getOrdinalStringForIndex:(nonnull NSNumber *)number;
#pragma mark - Validations
// Will validate passed string on corresponding regular expression

View File

@ -113,6 +113,12 @@
return mdn;
}
+ (nullable NSString *)getOrdinalStringForIndex:(nonnull NSNumber *)number {
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterOrdinalStyle;
return [formatter stringFromNumber:number];
}
#pragma mark - Validations
+ (BOOL)validateString:(nonnull NSString *)string withRegularExpression:(nonnull NSString *)regExpression {