Upgrade to Pro — share decks privately, control downloads, hide ads and more …

UIAccessibility

 UIAccessibility

Presentation I gave in March 2012 about UIAccessibility.

More Decks by Jeroen Leenarts (AppForce1)

Other Decks in Programming

Transcript

  1. Agenda • iOS Accessibility overview • VoiceOver demo • UIAccessibility

    & UIAccessibilityContainer • Some code + demo • Tips • Questions
  2. iOS Accessibility • Zoom. 
 Magnifies the entire device screen.

    • White on Black.
 Inverts the colors on the display. • Mono Audio.
 Combines the sound of the left and right channels into a mono signal played on both sides. • Speak Auto-text.
 Speaks the text corrections and suggestions iPhone makes while users type. • Voice Control.
 Allows users to make phone calls and control iPod playback using voice commands.
  3. VoiceOver • Screen reading technology • Intermediary between UI and

    user touch • Provides descriptions of elements and actions • Prevents accidents by describing what the user can do, is about to do and what results to expect
  4. VoiceOver • Label - A succinct label that identifies the

    accessibility element. • Value - The value of the accessibility element. • Hint - A brief description of the result of performing an action on the accessibility element. • Etc..
  5. Why the extra effort? • Increases user base • Allows

    app usage without seeing the screen • Might be a strict requirement • It’s just the right thing to do
  6. UIAccessibility & UIAccessibilityContainer • Most important objects to get to

    know when implementing accessibility • Every UIControl implements UIAccessibility • Want something custom? Implement the UIAccessibilityContianer protocol.
  7. UIAccessibility • Informal protocol • Allows objects to report their

    accessibility status • Reports accessibility information: label, value and hint. • Also allows reporting of other meta data: trait, frame, activationPoint
  8. - (NSString *)accessibilityHint { return @"Over te maken bedrag"; }

    ! - (NSString *)accessibilityLabel { return @"Bedrag"; } ! - (NSString *)accessibilityValue { NSString *value = [super accessibilityValue]; if (value != nil && value.length > 0) return [NSString stringWithFormat:@"€ %@", value]; else return nil; }
  9. [button setAccessibilityValue: [NSString stringWithFormat:@"%@ %@ %@", statusText, self.title, self.accountNumberLabel.accessibilityLabel]]; [button

    setAccessibilityTraits:UIAccessibilityTraitNone]; [button setAccessibilityHint: NSLocalizedString(@"Dubbelklik om zichtbaarheid te wijzigen.", @"Account cell: hide button accessibility hint")];
  10. What about traits? • Traits signify meta data about the

    object being made accessible. • Two types • What is it?
 UIAccessibilityTraitButton, UIAccessibilityTraitLink, UIAccessibilityTraitImage, etc • What state does it have?
 UIAccessibilityTraitNotEnabled, UIAccessibilityTraitUpdatesFrequently

  11. - (void) checkBoxButtonPressed:(id)sender { UIButton * const checkBoxButton = sender;

    if(self.isCheckBoxSelected) { ! checkBoxButton.accessibilityTraits = UIAccessibilityTraitButton; ! [checkBoxButton setImage: self.checkBoxImage forState:UIControlStateNormal]; self.checkBoxSelected = FALSE; } else { ! checkBoxButton.accessibilityTraits = UIAccessibilityTraitButton | UIAccessibilityTraitSelected; ! [checkBoxButton setImage: self.checkBoxSelectedImage forState:UIControlStateNormal]; self.checkBoxSelected = TRUE; } }
  12. Traits • UIAccessibilityTraitSummaryElement
 Read when the view appears. • The

    state related traits should be changed when the relevant UI state changes. • Every trait on an object will have some impact on VoiceOver
  13. UIAccessibility Container • Informal protocol • Allows a UIView subclass

    to make any number of objects it contains accessible
  14. UIAccessibility Container -(BOOL)isAccessibilityElement
 Should return NO when implementing the container

    protocol ! - (NSInteger)accessibilityElementCount ! - (id)accessibilityElementAtIndex:(NSInteger)index Returns a UIAccessibilityElement ! - (NSInteger)indexOfAccessibilityElement:(id)element
  15. // Returns NO because we are implementing the <UIAccessibilityContainer> informal

    protocol. -(BOOL)isAccessibilityElement { return NO; } ! - (NSInteger)accessibilityElementCount { return accessibleElements.count; } ! - (id)accessibilityElementAtIndex:(NSInteger)index { UIAccessibilityElement *element = [accessibleElements objectAtIndex:index]; return element; } ! - (NSInteger)indexOfAccessibilityElement:(id)element { // Returns accessibleElements is an NSArray filled with accessibility elements return [accessibleElements indexOfObject:element]; }
  16. • Returned from the UIAccessibilityContainer protocol accessibilityElementAtIndex: message. • Implements

    the UIAccessibility protocol • Proxy for screen elements which do not have their own VoiceOver, i.e: Custom drawing, Table cell accessory views • Warning: The frame value should be defined in screen coordinates UIAccessibilityElement
  17. - (void) checkBoxButtonPressed:(id)sender { UIButton * const checkBoxButton = sender;

    if(self.isCheckBoxSelected) { ! checkBoxButton.accessibilityTraits = UIAccessibilityTraitButton; ! if (UIAccessibilityIsVoiceOverRunning()) { UIAccessibilityPostNotification( UIAccessibilityAnnouncementNotification, NSLocalizedString(@"Contact wordt niet toegevoegd aan uw adresboek", @"")); } [checkBoxButton setImage: self.checkBoxImage forState:UIControlStateNormal]; self.checkBoxSelected = FALSE; } else { ! checkBoxButton.accessibilityTraits = UIAccessibilityTraitButton | UIAccessibilityTraitSelected; ! if (UIAccessibilityIsVoiceOverRunning()) { UIAccessibilityPostNotification( UIAccessibilityAnnouncementNotification, NSLocalizedString(@"Contact wordt toegevoegd aan uw adresboek", @"")); } [checkBoxButton setImage: self.checkBoxSelectedImage forState:UIControlStateNormal]; self.checkBoxSelected = TRUE; } }
  18. Tips • Convert a view coordinates to a screen coordinates

    ! • Set the frame when VoiceOver calls the accessibilityElementAtIndex: message CGRect frame = [self.contentView convertRect:frame toView:window]; frame = [window convertRect:frame toView:nil];