构建您iOS应用程序的无障碍特性

To be accessible, an iPhone application must supply information about its user interface elements to VoiceOver users. At a high level, this means you should make sure that:

要做到可用性,一个iPhone应用必须将用户界面元素中的相关信息提供给VoiceOver用户。更高层次上,这意味着您应该确保:

In addition to these fundamentals, there are also a few things you can do to enhance a VoiceOver user’s experience with table views and to make sure dynamic elements in your application are always accessible.

除了上述原则外,开发者还可以做一些事情来提升Voiceover用户对表格视图的体验,并确保应用中的动态元素始终无障碍。

让用户界面元素具有可访问性

As mentioned in Accessibility and VoiceOver a user interface element is accessible if it reports itself as an accessibility element. Although being accessible is not enough to make a user interface element useful to VoiceOver users, it represents the first step in the process of making your application accessible.

正如无障碍与VoiceOver所提及的,用户界面元素如果能告知其为无障碍元素,那么该元素是可访问性的。尽管可访问并不能足够让用户界面元素对Voiceover用户可用,但这是应用程序进行无障碍化过程的第一步。

As stated in iOS Accessibility API and Tools, standard UIKit controls and views are automatically accessible. If you use only standard UIKit controls, you probably don’t have to do much additional work to make sure your application is accessible. In this case, your next step is to ensure that the default attribute information supplied by these controls makes sense in your application. To learn how to do this, see Supply Accurate and Helpful Attribute Information.

也如iOS无障碍API及工具中所述,标准的UIKit控件和视图是自动具有可访问性的。如果只使用了标准的UIKit控件,开发者可能不需要太多其他工作来确保应用的无障碍。在这种情况下,下一步工作是确保应用中这些控件提供的默认属性信息是有意义的。详情参见提供准确和帮助性的属性信息

If you create custom views that display information or with which users need to interact, you must ensure the accessibility of these views yourself. After you’ve done this, you need to make sure these views supply accessibility information that helps people use them (see Supply Accurate and Helpful Attribute Information).

如果创建一个自定义视图来展示信息或是与用户进行交互,开发者必须确保这些视图的无障碍特性。在完成这些之后,开发者还需要确保这些视图提供的无障碍信息可以帮助到用户。(参见提供准确和有用的属性信息)。

From the perspective of accessibility, a custom view is either an individual view or a container view. An individual view does not contain any other views that need to be accessible. For example, a custom subclass of UIControl that displays an icon and behaves like a button does not contain any other elements with which the user can interact, apart from the button itself. Read Make Custom Individual Views Accessible to learn how to make an individual view accessible.

从无障碍的角度来说,自定义视图可能是一个独立的视图也可能是一个容器视图。独立视图(individual view)不包含其他需要无障碍化的视图。例如,一个自定义UIControl子类会显示一个图标,并且具有按钮的行为,但是除了按钮本身,其并不包含任何可以与用户进行交互的元素。请阅读让自定义的独立视图具有无障碍特性了解如何让一个独立视图具有无障碍特性。

A container view, on the other hand, contains other elements with which users can interact. For example, in a custom subclass of UIView that performs its own drawing of geometric shapes, the shapes represent elements with which users can interact, and which are distinct from the container view. Such separate elements within a container view are not automatically accessible (because they are not subclasses of UIView) and do not provide any accessibility information. To learn how to make the contents of a container view accessible, read Make the Contents of Custom Container Views Accessible.

另一方面,容器视图包含其他可以和用户进行交互的元素。例如,在一个自定义UIView子类中绘制一个几何图形,用户可以与该图形呈现的元素进行交互,这与容器视图不同。容器视图内的独立元素不能自动获得无障碍特性(因为它们不是UIView的子类),也不会提供任何无障碍信息。请阅读让自定义容器视图的内容具有无障碍特性了解如何让容器视图的内容具有无障碍特性。

让自定义的独立视图具有无障碍特性

If your application contains a custom individual view with which users need to interact, you must make the view accessible. (Recall that an individual view is a view containing no other views with which users interact.)

如果应用包含一个需要与用户进行交互的自定义独立视图,开发者必须确保这个视图的无障碍特性。(回想一下,一个独立视图是指:一个视图不包含其它可与用户交互的视图。

In addition to using Interface Builder to make a custom individual view accessible, there are two programmatic ways to do this. One way is to set your custom view’s accessibility status in the code that instantiates it. The following code snippet shows how to do this:

除了使用Interface Builder构建自定义视图的无障碍特性,还可以通过两种编程方法让自定义独立视图具有无障碍特性。第一种方法是:在实例化自定义视图的代码中设置其无障碍状态。如下面的代码片段所示:

@implementation MyCustomViewController
- (id)init
{
  _view = [[[MyCustomView alloc] initWithFrame:CGRectZero] autorelease];
  [_view setIsAccessibilityElement:YES];
 
/* 此处设置属性*/
}

Another way is to implement the isAccessibilityElement method of the UIAccessibility protocol in the implementation of your custom subclass. The following code snippet shows how to do this:

另一种方法是在您的自定义子类实现中,UIAccessibility协议中使用isAccessibilityElement。如下面的代码片段所示:

@implementation MyCustomView
  /*此处使用属性方法 */
 
- (BOOL)isAccessibilityElement
{
   return YES;
}

让自定义容器视图的内容具有无障碍特性

If your application displays a custom view that contains other elements with which users interact, you need to make the contained elements separately accessible. At the same time, you need to make sure that the container view itself is not accessible. The reason is that users interact with the contents of the container, not with the container itself.

如果应用中展示了一个自定义视图,包含其他与用户交互的元素,则需要让包含元素分别具有无障碍特性。同时,开发者必须让容器视图本身不再具有无障碍特性,因为用户是与容器中的内容进行交互,不是和容器本身交互。

To accomplish this, your custom container view should implement the UIAccessibilityContainer protocol. This protocol defines methods that make the contained elements available in an array.

为此,自定义的容器视图应该实现UIAccessibilityContainer协议。这个协议会定义一些方法让被包含元素存放于一个数组中。

The following code snippet shows the partial implementation of a custom container view. Note that this container view creates the array of accessible elements only when methods of the UIAccessibilityContainer protocol are called. As a result, if iPhone accessibility is not currently active, the array is not created.

如下代码片段展示了一个自定义容器视图的部分实现。注意,这个容器视图只会在调用UIAccessibilityContainer协议时,才会创建无障碍元素数组。因此,如果iPhone的无障碍状态并没有被激活,那就不会创建该数组。

表 2-1  实现自定义容器中的内容做为独立的无障碍元素

@implementation MultiFacetedView
- (NSArray *)accessibleElements
{
   if ( _accessibleElements != nil )
   {
      return _accessibleElements;
   }
   _accessibleElements = [[NSMutableArray alloc] init];
 
   /*  创建一个无障碍元素展示第一个被包含的元素,并初始化它做为MultiFacetedView的组件*/
   UIAccessibilityElement *element1 = [[[UIAccessibilityElement alloc] initWithAccessibilityContainer:self] autorelease];
 
   /* 此处设置第一个包含元素的属性*/
   [_accessibleElements addObject:element1];
 
   /* 为第二个包含元素执行相同步骤*/
   UIAccessibilityElement *element2 = [[[UIAccessibilityElement alloc] initWithAccessibilityContainer:self] autorelease];
 
   /*此处设置第二个包含元素的属性*/
   [_accessibleElements addObject:element2];
 
   return _accessibleElements;
}
 
/* 容器本身并不具有无障碍特性,所以MultFacetedView在isAccessiblityElement中应该返回NO*/
- (BOOL)isAccessibilityElement
{
   return NO;
}
 
/* 如下方法实施UIAccessibilityContainer协议 */
- (NSInteger)accessibilityElementCount
{
   return [[self accessibleElements] count];
}
 
- (id)accessibilityElementAtIndex:(NSInteger)index
{
   return [[self accessibleElements] objectAtIndex:index];
}
 
- (NSInteger)indexOfAccessibilityElement:(id)element
{
   return [[self accessibleElements] indexOfObject:element];
}
@end

提供准确和有用的属性信息

There are two parts to the process of supplying attribute information for accessible elements:

提供准确和有用的属性信息有以下两个步骤:

If you use custom views, you must supply all appropriate attribute information for them. For guidance, see Crafting Useful Labels and Hints, Guidelines for Creating Hints, and Identifying Appropriate Traits.

如果使用自定义的视图,开发者必须为它们提供适当的属性信息。请参阅制作有用的标签和提示创建提示指南定义恰当的特质

Even if you use only standard UIKit controls and views, you might find that some of the default attribute information they supply could be enhanced to make more sense in the context of your application. For more information, see Enhancing Default Attribute Information.

即使只是用标准的UIKit控件和视图,也可能找到比默认提供的属性信息更适合应用环境的内容。更多信息请阅读“优化默认属性信息”。

If you need to supply or change accessibility attributes on either standard or custom UI elements, you can do so either in Interface Builder (see Defining Custom Attribute Information in Interface Builder) or programmatically (see Defining Custom Attribute Information Programmatically).

无论是标准还是自定义的UI元素,如果需要提供或者更改其无障碍属性,开发者都可以使用Interface Builder(请参阅在Interface Builder中自定义属性信息)或者编程化处理(请参阅 编程化处理自定义属性信息)。

优化默认属性信息

As part of the built-in accessibility of standard UIKit controls and views, iOS also provides default attribute information that describes these elements to VoiceOver users. In most cases, this information is appropriate for applications that use the standard controls and views. However, there might be times when supplying custom attribute information can enhance a VoiceOver user’s experience with your application:

作为标准UIKit控件和视图内建无障碍特性的一部分,iOS也为这些元素提供了默认属性信息,这些信息可以向VoiceOver用户描述这些元素。大多数情况下,应用如果使用标准控件和视图,这种信息是合适的。但是,自定义属性信息可以增强VoiceOver用户的体验:

  • If you use a standard UIKit control or view that displays a system-provided icon or title, first make sure you’re using it in accordance with its intended purpose (see iOS Human Interface Guidelines for more information). Then, decide whether the default label attribute accurately conveys the result of using that control or view in your application. If not, consider providing a hint attribute.

    如果用一个标准UIKit控件和视图显示系统提供的图标和标题,开发者首先需要确认是以预期的目的使用它(请参阅“iOS人机界面指南”了解更多信息)。然后认真考虑,在应用中,默认的标签属性是否准确地传达结果,如果没有,考虑提供一个提示属性。

    For example, if you place an Add button in your navigation bar by using the system-provided Add (+) icon in a UIBarButtonItem object, you get the default label attribute, Add, automatically. If it’s always obvious which item the user is adding when they activate this button, there’s no need to provide a hint attribute. But if there might be confusion, you should consider providing a custom hint that describes the result of using that control in your application, such as "Adds an account" or "Adds a comment."

    举例来说,如果在UIBarButtonItem对象中,开发者使用系统提供的加(+)图标,在导航栏中放置一个添加按钮,它会自动包含一个默认的标签属性:添加。如果用户可以明确地知道每次点击这个按钮会添加哪个项目,那就不需要提供提示属性。但是如果可能产生误解,开发者应该在应用中提供一个自定义的提示,用以描述使用该按钮的效果,比如“添加一个账户”或者“添加一个评论”。

  • If you display a custom icon or image in a standard UIKit view, such as a UIButton object, you need to supply a custom label attribute that describes it.

    如果您在标签的UIKit视图中显示一个自定义的图标或者图像,比如UIBarButtonItem对象,需要提供一个自定义的标签属性用以描述它。

制作有用的标签和提示

When VoiceOver users run your application, they rely on the descriptions VoiceOver speaks to understand what your application does and how to use it. Because these descriptions represent the bulk of the VoiceOver user’s experience with your application it’s essential that they be as accurate and helpful as possible. The guidelines in this section help you create labels and hints that will make your application easy and enjoyable for people with disabilities to use.

当VoiceOver用户使用应用时,他们依赖VoiceOver的描述了解应用的作用以及如何使用,由于这些描述代表了大量的VoiceOver用户对于应用的体验,所以有必要尽可能让其准确有用。该指南会帮助开发者创建有用的标签和提示,让应用对于残障人士来说更加简单易用。

创建标签指南

The label attribute identifies the user interface element. Every accessible user interface element, standard and custom, must supply content for the label attribute.

标签属性定义了用户界面中的元素,无论是标准的还是自定义的,每个无障碍用户界面元素都必须为标签属性提供内容。

A good way to determine what a label should convey is to think about what a sighted user infers about your application just by looking at it. If you’ve designed a good user interface, sighted users should know what a control or view does in the current application context by reading its title or understanding its icon. This is the information you need to make available to VoiceOver users in the label attribute.

判定标签应该传达什么内容的一个好办法,就是思考视觉用户通过视觉能够看到什么。如果用户界面设计地很好,视觉用户应该可以通过阅读标题或理解图标,了解在当前应用中控件和视图的作用。这些就是VoiceOver用户可从标签属性获取到的信息。

If you provide a custom control or view, or if you display a custom icon in a standard control or view, you need to provide a label that:

如果提供一个自定义的控件和视图,或者开发者在标准控件或视图中展示一个自定义的图标,需要提供如下的标签(label):

  • Very briefly describes the element. Ideally, the label consists of a single word, such as Add, Play, Delete, Search, Favorites, or Volume.

    非常简要地描述元素:理想化的标签(label)是由一个单词构成,比如,添加、播放、删除、搜索、收藏、音量。

    Strive to design your application so that a single word identifies an element and makes its usage obvious in the current context. Sometimes, however, it might be necessary to use a brief phrase to properly identify an element. When this is the case, create a very short phrase, such as “Play music,” “Add name,” or “Add to event.”

    努力设计应用,尽量用一个单词标识一个元素,并能使它在当前环境下的作用显而易见。然而,有时候可能需要使用一个简单的短语才能标识一个元素。遇到这种情况,创建一个短的句子,比如“播放音乐”、“添加姓名”或者“添加事件”。

  • Does not include the type of the control or view. The type information is contained in the traits attribute of the element and should never be repeated in the label.

    不要包含控件或者视图的类型:这类信息被包含在元素的特质属性中,应永远不重复出现在标签中(label)。

    For example, if you include the control type in the label of an Add button, VoiceOver users hear “Add button button” every time they access that control. This experience would quickly become annoying and might motivate users to stop using your application.

    例如,如果在一个添加按钮的标签中,包含控件类型,VoiceOver用户每次访问该控件的时候都会听到“添加按钮按钮”,这种体验非常讨厌,可能刺激用户停止使用您的应用。

  • Begins with a capitalized word. This helps VoiceOver read the label with the appropriate inflection.

    单词首字母大写:可以帮助VoiceOver用适当的音调读取标签。

  • Does not end with a period. The label is not a sentence and therefore should not end with a period.

    不要在结束处用句号:标签不是一句话,因此不应该使用句号结束。

  • Is localized. Be sure to make your application available to as wide an audience as possible by localizing all strings, including accessibility attribute strings. In general, VoiceOver speaks in the language that the user specifies in International settings.

    本地化:本地化无障碍属性中的所有字符串,一定能让应用被更广泛的受众使用。通常情况,VoiceOver是以用户设置的语言进行朗读。

创建提示指南

The hint attribute describes the results of performing an action on a control or view. You should provide a hint only when the results of an action are not obvious from the element’s label.

提示属性描述的是:在控件或视图上执行一个动作的结果。当元素标签无法明确指出动作结果的时候,应该给出一个提示。

For example, if you provide a Play button in your application, the context in which the button appears should make it easy for users to understand what happens when they tap it. However, if you allow users to play a song by tapping the song title in a list, you might want to provide a hint that describes this result. The reason is that the label of the list item describes the item itself (in this case, the song title), not what happens when a user taps it.

例如:在应用中提供一个播放按钮,按钮周边环境可让用户很容易明白,他们按下按钮时会发生什么。但是,如果允许用户通过轻敲歌曲列表中歌名播放歌曲,开发者应该提供一个提示用以描述结果,因为列表项的标签仅介绍自己的属性(此例中指歌名),用户点击时不知道会发生什么。

If the results of a user’s action on a control or view are not clearly implied by its label, create a hint that:

如果用户在控件或者视图上的动作结果,不能通过标签明确的表明,创建一个这样的提示:

  • Very briefly describes the results. Even though few controls and views need hints, strive to make the hints you do need to provide as brief as possible. Doing so decreases the amount of time users must spend listening before they can use the element.

    尽量简单介绍结果:尽管没有多少控件和视图需要提示,也应尽可能的提供简短的介绍。避免了用户还没使用元素,就浪费大量时间去听取相关信息。

    That said, however, avoid sacrificing clarity and good grammar for brevity. For example, changing “Adds a city” to “Adds city” does not significantly decrease the length of the hint, but does make it sound awkward and a bit less clear.

    但是,不要为了提示的简短,而丧失语法的清晰和优雅。例如,将“添加一个城市”,改为“添加城市”,这并不意味着提示的长度简短了,反而听起来更别扭,并且表意不够清晰。

  • Begins with a verb and omits the subject. Be sure to use the third-person singular declarative form of a verb, such as “Plays,” and not the imperative, such as “Play.” You want to avoid using the imperative, because using it can make the hint sound like a command. For example, you don’t want to tell users to “Play the song”; instead, you want to tell users that tapping the element “Plays the song.”

    动词开头,省略主语:确认使用第三人称单数的动词形式。例如“Plays,” 而不是强制的,如“Play.”。要避免使用命令语式,因为其放在提示中,像是一条命令。比如,不要告诉用户“Play the song”,要告诉用户按下元素会“Plays the song.”。

    To help you find the right word, imagine that you’re describing the use of a control to a friend. You might say something like “Tapping this control plays the song.” Often, you can use the second phrase in such a sentence (in this case, “Plays the song”) as a hint.

    要想找到正确的用词,想象一下,您正在为一位朋友介绍一个控件的用法,可能会这样说:“点击这个控件播放歌曲”。通常该句话的第二个短语(此例中为“播放歌曲”)可以作为一个提示。

  • Begins with a capitalized word and ends with a period. Even though a hint is a phrase, not a sentence, ending the hint with a period helps VoiceOver speak it with the appropriate inflection.

    大写字母开头,句号结尾:即使提示是一个短语,不是一个句子,也要在提示末尾使用句点,这样有助于VoiceOver以适当的语气进行播报。

  • Does not include the name of the action or gesture. A hint does not tell users how to perform the action, it tells users what will happen when that action occurs. Therefore, do not create hints such as “Tap to play the song,” “Tapping purchases the item,” or “Swipe to delete the item.”

    不要包含行为的名称或手势:一个提示不用告诉用户如何执行该动作,它告诉用户的是当行为发生时会发生什么。因此,不要创建类似于“存储保存您的修改”或者“后退返回到之前的屏幕”的提示。

    This is especially important because VoiceOver users can use VoiceOver-specific gestures to interact with elements in your application. If you name a different gesture in a hint, it would be very confusing.

    这极其重要,因为VoiceOver用户使用特定手势与应用进行交互。如果在一个提示中命名了不同的手势,会造成一定的混淆。

  • Does not include the name of the control or view. The user gets this information from the label attribute, so you should not repeat it in the hint. Therefore, do not create hints such as “Save saves your edits” or “Back returns to the previous screen.”

    不要包含控件和视图的名称:用户从标签属性里得到信息,所以开发者不应该在提示中重复相关信息。因此,不要创建类似于这样的提示“存储保存您的修改”或者“后退返回到之前的屏幕”。

  • Does not include the type of the control or view. The user already knows whether, for example, the control or view behaves like a button or a search field, because this information is available in the element’s traits attribute. Therefore, do not create hints such as “Button that adds a name” or “Slider that controls the scale.”

    不要包含控件和视图的类型:用户已经知道控件表现为一个按钮或者搜索域,因为该信息可从元素特质获取。因此,不要创建类似于“按钮用于添加名称”或者“滑动用于控制比例”的提示。

  • Is localized. As with accessibility labels, hints should be available in the user’s preferred language.

    本地化:与无障碍标签类似,提示应该可以读取用户的偏好语言。

定义恰当的特质

The traits attribute contains one or more individual traits that, taken together, describe the behavior of an accessible user interface element. Because some individual traits can be combined to describe a single element, the element’s behavior can be precisely characterized.

特质属性包含一个或者多个独立特质,共同描述一个无障碍用户界面元素的行为。由于一些独立的特性可以组合起来一起描述一个单独元素,因此一个元素的行为可以被准确地表述。

A standard UIKit control, such as a button or text field, provides default content in the traits attribute. If you use only standard UIKit controls in your application (and do not customize their behavior in any way), you do not have to make any changes to the traits attribute of these controls.

一个标准的UIKit控件,如一个按钮或者文本域,在特质属性中会提供默认的内容。如果在应用中仅用标准UIKit控件(特指没有用任何方式自定义其行为),这些控件的特质属性不会有任何变化。

If you customize the behavior of a standard control, you might need to combine a new trait with the control’s default traits. If you create a custom control or view, you need to provide content for the element’s traits attribute.

如果是自定义行为的标准控件,开发者可能需要将某个新的特质与该控件默认的特质组合。如果创建自定义的控件视图,开发者需要提供该元素特质属性的内容。

The UI Accessibility programming interface defines 12 individual traits, some of which can be combined. Some traits characterize an element by identifying its behavior with the behavior of a particular type of control (such as a button) or type of object (such as an image). Other traits characterize an element by describing a specific behavior the element can exhibit, such the ability to play sound.

UI无障碍编程接口定义了12个独立的特质,其中某些是可以被组合的。某些特质是通过特定控件类型的行为标识一个元素(如按钮)或者对象类型(如图像)。其它特质通过描述特定元素的展示行为标识元素,如播放声音的功能。

You use the following traits to characterize elements in your application:

如下的特质可用于在应用中标识元素:

  • 按钮(Button)

  • 链接(Link)

  • 搜索域(Search Field)

  • 键盘按键(Keyboard Key)

  • 静态文本(Static Text)

  • 图像(Image)

  • 播放声音(Plays Sound)

  • 选中(Selected)

  • 总结元素(Summary Element)

  • 常态更新(Updates Frequently)

  • 不可用(Not Enabled)

  • 空(None)

In general, traits that correspond to controls can successfully be combined with traits that describe behaviors. For example, you might combine the Button trait with the Plays Sound trait to characterize a custom control that behaves like a button and plays sound when it is tapped.

通常,控件相对应特质能够结合描述行为的特质,例如,“按钮”特质可能和“播放音乐”特质用以表述一个自定义控件,其表象是一个按钮,点击即可播放音乐。

For the most part, you should consider the traits that correspond to particular controls, specifically, the Button, Link, Search Field, and Keyboard Key traits, to be mutually exclusive. That is, you should not use more than one of these traits to characterize an element in your application. Instead, think about which one of these four traits corresponds most closely to the element in your application. Then, if your element has additional behaviors, you can combine the first trait with one of the behavioral traits.

大多数情况下,应该考虑特质对应特定控件,尤其是,按钮、链接、搜索域、键盘键的特质,是互斥的。这时,不应该使用超过一个特质去表述应用中的某个元素,如果此元素有其它行为,可以将第一个特质和某一个行为特质结合。

For example, suppose you display an image in your application that responds to a user’s tap by opening a link in Safari on iPhone. You could characterize this element by combining the Image and Link traits. Another example is a keyboard key that modifies other keyboard keys when it is tapped. You could characterize this element by combining the Keyboard Key and Selected traits.

例如,假设显示在应用中的一个图像,其响应的是,当用户点击时会在iPhone中的Safari打开一个链接,开发者应该通过结合图像和链接的特质表述该元素。另如,一个键盘键当点击时修改其它键盘键,开发者应该通过结合键盘键和选中的特质标识该元素。

To see some examples of how traits characterize controls, you can use Accessibility Inspector to see the default traits that are set on the standard controls. For information on how to use Accessibility Inspector, read Debug Accessibility in iOS Simulator with the Accessibility Inspector.

了解如何标识控件的案例,可以用Accessibility Inspector看在标准控件中已被设定的默认特质。更多关于如何使用Accessibility Inspector,请参阅通过Accessibility Inspector在iOS Simulator无障碍排错

在Interface Builder中自定义属性信息

When you install iOS SDK 3.0, you get a version of Interface Builder that includes features that help you make your application accessible. If your application contains standard UIKit controls and views, you might be able to do all your accessibility work in Interface Builder.

安装iOS SDK 3.0后,获得的Interface Builder版本包含帮助应用达到无障碍特性的功能。如果应用包含标准UIKit的控件和视图,可通过Interface Builder做所有的无障碍工作。

Using Interface Builder, you can set an element’s accessibility status and provide custom content for the label, hint, and traits attributes. To do this, select the user interface element in your nib file and open the Identity inspector. Reveal the Accessibility section in the inspector and you should see something like Figure 2-1:

使用Interface Builder,可以设置元素的无障碍状态,并且为标签(label)和特质(traits)属性提供自定义内容。为此,在nib文件中选择用户界面元素,并且打开Identity inspector,在inspector中的Accessibility处,应该可以看到如图2-1所示内容:

图 2-1  显示在Interface Builder中的标准文本域的默认无障碍信息

As you can see in Figure 2-1, the standard text field used in the nib file is accessible by default and includes default information for the label, hint, and traits attributes. (Note that, for a text field that displays placeholder text, the default label is the placeholder text.) You can change any of these default values by supplying new information in the Identify inspector, as shown in Figure 2-2. (Figure 2-2 also shows how Accessibility Inspector displays the accessibility information for the text field. See Debug Accessibility in iOS Simulator with the Accessibility Inspector to learn about Accessibility Inspector.)

图2-1所示,用于nib文件中的标准文本域默认是无障碍的,并且标签(label)、提示(hint)、特质(traits)的属性中包含默认的信息,(注意,文本域显示占位符文本,默认的标签就是占位符文本),在Identify inspector中可以提供新的信息改变任何默认值。如在图2-2所示,(图2-2显示的也是Accessibility Inspector如何显示文本域中的无障碍信息。参阅通过Accessibility Inspector在iOS Simulator无障碍排错)。

图 2-2  在Interface Builder中提供无障碍信息

编程化处理自定义属性信息

If you prefer, you can supply custom information for attributes programmatically. You might want to do this if you’re not using Interface Builder at all or if you generate your views in code instead of using Interface Builder.

如果愿意,开发者可以通过编程为属性提供自定义信息。如果开发者完全不用Interface Builder或者更喜欢在代码中生成视图,这可能是开发者想用的方法。

As described in Make Custom Individual Views Accessible, you can set accessibility information in the implementation of your view subclass or in the code that instantiates the view. Both techniques are valid, but there is one reason why you might want to implement attribute methods in your subclass instead of setting attributes in the instantiation code: If your view displays data that is dynamic or that changes frequently, such as the time of day, you should implement the subclass methods to return fresh data as needed. For those situations, if you only set attributes when you instantiate the subclass, the returned data is likely to be out of date.

让自定义的独立视图具有无障碍特性中介绍过,开发者可以在视图子类或在代码里实例化视图设置无障碍信息。两种方法都是有效的,但是为什么开发者可能需要在子类中实现属性方法而不是通过代码实例化实现,原因是:如果显示数据是动态的,或者频繁改变,如日期,开发者应该实现子类方法返回需要的刷新数据。在这些情况下,如果仅在实例化子类时设置属性,返回的数据可能是过期的。

The code snippets in this section build on those in Make Custom Individual Views Accessible, by including some of the attribute-specific methods. For example, if you want to implement accessibility methods in your subclass, you would write code similar to that in Listing 2-2.

此章节的代码片段是基于让自定义的独立视图具有无障碍特性,包含一些属性特有的方法。例如:如果开发者想在子类中实现无障碍方法,将会用到类似表2-2的代码:

表 2-2  在自定义子类实现中提供属性信息

@implementation MyCustomView
- (BOOL)isAccessibilityElement
{
   return YES;
}
 
- (NSString *)accessibilityLabel
{
   return NSLocalizedString(@"MyCustomView.label", nil);
}
 
/* 这个自定义控件的表像为一个按钮*/
- (UIAccessibilityTraits)accessibilityTraits
{
   return UIAccessibilityTraitButton;
}
 
- (NSString *)accessibilityHint
{
   return NSLocalizedString(@"MyCustomView.hint", nil);
}
@end

If you want to use the property-setting methods of the UIAccessibility protocol in the code that instantiates your custom view, you can write code similar to that in Listing 2-3.

如果您要在代码中使用UIAccessibility协议的属性设定方法,实例化自定义视图,将会用到类似于表2-3中的代码。

表 2-3  在代码中提供属性信息,实例化自定义的子类对象

@implementation MyCustomViewController
- (id)init
{
  _view = [[MyCustomView alloc] initWithFrame:CGRectZero];
 
  [_view setIsAccessibilityElement:YES];
  [_view setAccessibilityTraits:UIAccessibilityTraitButton];
  [_view setAccessibilityLabel:NSLocalizedString(@"view.label", nil)];
  [_view setAccessibilityHint:NSLocalizedString(@"view.hint", nil)];
}

优化表格视图无障碍特性

If your application displays a table view in which each cell contains items other than (or in addition to) text, there are a few things you can do to make it more accessible. Similarly, if your table view displays more than one piece of information per row, you can enhance a VoiceOver user’s experience by aggregating the information in a single, easy-to-understand label.

如果应用中展示了一个表格,每个单元格中不只包含文本(或除了文本)条目,开发者可以做某些事情让其无障碍。同样地,如果表格视图中每行展示的信息不止一条,那可以把这些信息整合到一条易于理解的标签中,以优化VoiceOver用户的体验。

If the table cells in your application contain a mix of different elements, determine whether users interact with each cell as a unit, or with individual elements inside the cell. If users need to access individual elements inside the cell, you should:

如果应用中的表格单元包含不同元素的混合,检查用户是与单元进行交互还是与单元里的独立元素进行交互。如果用户需要访问单元里的独立元素,开发者应该:

You’ve probably recognized that a table cell that contains multiple items, such as text and controls, fits the criteria of a container view, as defined by the UI Accessibility programming interface. However, you do not have to identify the cell as a container view or implement any of the methods of the UIAccessibilityContainer protocol, because the table cell is automatically designated as a container.

开发者可能已经意识到表格单元中可能会包含多个项目,如文本和控件,被UI无障碍编程接口所定义,匹配容器视图的标准。然而,开发者不必将单元格标识为容器视图,或实现UIAccessibilityContainer协议中的任何方法,因为表格单元被自动指派为一个容器。

If your table contains cells that provide information in discrete chunks, you should consider combining the information from these chunks in the label attribute. When you do this, VoiceOver users can get the meaning of the cell’s contents with one gesture, instead of having to access each piece of information separately.

如果表格中包含单元格,这些单元格在离散组块中提供信息,开发者应该考虑从这些标签属性的组块中组合信息。当实现该功能,VoiceOver用户可以仅使用一个手势就能获取单元格内容的意义,而不需要单独访问每个独立块中的信息。

A good example of how this can work is in the built-in Stocks application. Instead of providing the company name, current stock price, and change in price as separate strings, Stocks combines this information in the label, which might sound like this: “Apple Inc., $432.39, up 1.3%." Notice the commas in this label. When you combine discrete pieces of information in this way, you can use commas to tell VoiceOver to pause briefly between phrases, making it easier for users to understand the information.

用一个很好的例子解释该功能的效果:内建股票应用,它不用单独字符串去提供公司名、当前股票价格和价格波动,而是组合到一个标签(label)中,这样听起来类似:“苹果公司,432.39美元,涨幅1.3%。”。注意标签中的逗号,当结合多个片段的时候,可以使用逗号,这样VoiceOver就会在每个逗号短暂停留,让用户更容易理解信息。

Here’s a code snippet that shows how to combine the information in the labels of two separate elements into a single label that describes both:

此处的代码片段展示了如何组合两个独立元素中的信息到一个单独标签:

@implementation CurrentWeather
/* 该视图提供了天气信息,它包涵一个城市子视图和一个温度子视图,每个视图有独立标签 */
- (NSString *)accessibilityLabel
{
    NSString *weatherCityLabel = [self.weatherCity accessibilityLabel];
    NSString *weatherTempLabel = [self.weatherTemp accessibilityLabel];
 
    /* 结合城市和温度的信息,VoiceOver用户可以使用一个手势来获取天气信息*/
    return [NSString stringWithFormat:@"%@, %@", weatherCityLabel, weatherTempLabel];
}
@end

让动态元素具有无障碍特性

If user interface elements in your application can change dynamically, you need to make sure that the accessibility information they supply is accurate and up-to-date. You also need to send notifications when changes occur in the layout of application screens, so that VoiceOver can help users navigate the new layout. The UI Accessibility programming interface provides two notification types you can use when these kinds of changes occur on the screen. (To learn about these notifications, see "Notifications” in UIAccessibility Protocol Reference.)

如果应用中的界面元素会动态改变,开发者需要确认元素提交的无障碍信息是准确及时的。当应用屏幕布局改变发生时,需要发送一个通知,这样VoiceOver能够帮助用户导航新布局。UI无障碍编程接口提供两个通知类型,可以用在这类屏幕改变事件发生的情况下。(了解这些通知,请在 UIAccessibility协议参考中的“通知”。)

If user interface elements can be in different states depending on other conditions in your application, you need to add logic to your code that returns the correct accessibility information for each state an element can be in. Because these changes can occur as the result of user actions, it’s best to add this logic to a subclass’s implementation, not to the code that instantiates the subclass.

如果用户界面元素根据不同应用条件下有不同的状态,那开发者需要在代码中加入返回元素所有状态对应无障碍信息的逻辑。由于这些改变是用户的动作的结果,所以最好把逻辑添加到子类实现中,而不是实例化子类的代码中。

The following code shows how to handle dynamic state changes and how to send a notification when a screen layout changes. The code represents the implementation of a UIView subclass that behaves like a custom keyboard key. The key’s accessibility label changes depending on whether the instance represents a letter or other type of character, and on whether a shift key is currently selected. The key also returns different accessibility traits, depending on what type of keyboard key it represents and whether it is currently selected. Note that the code in Listing 2-4 assumes that there are a number of methods that query the state of the keyboard.

下面的代码展示了如何处理动态状态的改变以及如何在屏幕布局发生改变时发送通知。代码中的UIView子类的行为类似一个自定义键盘按键。按键的无障碍标签会根据实例是否代表一个字母或其他类型的字符,和shift键是否按下来进行改变。按键也会根据实例内容和选中状态返回不同的无障碍特性。注意,表2-4的代码假设会有许多方法查询键盘的状态:

表 2-4  为当前情况返回正确的无障碍信息,并且发送布局改变通知

@implementation BigKey
- (NSString *)accessibilityLabel
{
   NSString *keyLabel = [_keyLabel accessibilityLabel];
   if ( [self isLetterKey] )
{
      if ( [self isShifted] )
      {
         return [keyLabel uppercaseString];
      }
      else
      {
         return [keyLabel lowercaseString];
      }
   }
   else
   {
      return keyLabel;
   }
}
 
- (UIAccessibilityTraits)accessibilityTraits
{
   UIAccessibilityTraits traits = [super accessibilityTraits] | UIAccessibilityTraitKeyboardKey;
 
   /*是否这是一个shift键,并被按下,用户需要知道shift当前是有效的*/
   if ( [self isShiftKey] && [self isSelected] )
   {
      traits |= UIAccessibilityTraitSelected;
   }
 
   return traits;
}
 
- (void)keyboardChangedToNumbers
{
   /* 此处代码,执行一个数字键盘的变化 */
 
   /*发送一个屏幕布局改变的通知。*/
 
   UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
}
@end

让非文本数据具有无障碍特性

Sometimes your application displays data that’s not automatically compatible with the way accessibility works. For example, if you display an image, you should provide a description of it in its accessibility label so that VoiceOver users can understand the information the image conveys. Or, if you provide information in a graphical way, such as a rating system that displays stars, you should make sure the accessibility label conveys the meaning behind the graphical representation.

有时应用会展示那些不是自动兼容无障碍方法的数据。例如,如果展示一个图像,开发者应该在它的无障碍标签中提供它的描述,这样VoiceOver用户就可以理解图像传达的信息。或者,如果使用图形方式提供信息,比如显示星级的评价系统,开发者应该确认无障碍标签传达了图形所表达的意思。

The following code snippet uses the example of a custom view that draws the number of stars that corresponds to the rating of an item. The code shows how this view returns an appropriate accessibility label, depending on how many stars it draws.

如下的代码段使用自定义视图样例展示了与评分条目对等的星级条目。该代码展示了视图如何根据绘制的星星数量返回一个恰当的无障碍标签。

@implementation RatingView
/* Other subclass implementation code here. 在此处实现其它子类的代码。*/
 
- (NSString *)accessibilityLabel
{
   /*_starCount是一个实例化变量,包含了画多少颗星星*/
   NSInteger starCount = _starCount;
   if ( starCount == 1 )
   {
      ratingString = NSLocalizedString(@"rating.singular.label", nil); //此处,ratingString是星数
   }
   else
   {
      ratingString = NSLocalizedString(@"rating.plural.label", nil); // 此处,ratingString是星数
   }
 
   return [NSString stringWithFormat:@"%d %@", starCount, ratingString];
}
@end