motion-accessibility 3.0.3 → 3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 819af2675decd0bce413fe497d7383140fe6002e
4
- data.tar.gz: adf5becb4d1972e68aa725b484e634ea37ec0d69
3
+ metadata.gz: ac5d11d4ddac910e4320eda4b40d2378f2c34fbd
4
+ data.tar.gz: 0cb56cc757c04b0f671217d890989294793b90b4
5
5
  SHA512:
6
- metadata.gz: abe03c5e214f4a09599027896d52ce4b53b2c299b40410976989e65ebd142532a32713a8385634253aa6907c74afbabaa463e3a35034096e428e68970595f092
7
- data.tar.gz: ba04d69277795cb9a4aadc31a5d4a18602a0664dd0cab221aeed4610d6852a94e6bb2268955c19aa4af440dcbf28f99bcd973a35f6f353b2d82286e4e77f998b
6
+ metadata.gz: 1fafbc0d2fceb2412f1539036230afe52d1bd4d679b403df5ef14a56bbc6c26e6856143d0784497e55a82be68a4d565e947b83b6712f0591331b4559c638be9d
7
+ data.tar.gz: 32716ec1402e0f7625baac2d41afd4740ecd217820bac7e90cf38fd8aaf12508a7473134e2d55e57f3300d64a4c1894aa11f37c4c8abfe55a5f641f61043fcdc
data/README.md CHANGED
@@ -4,7 +4,14 @@
4
4
 
5
5
  https://github.com/austinseraphin/motion-accessibility
6
6
 
7
- Motion-accessibility provides the tools needed for sighted and blind iOS RubyMotion developers to make their apps more accessible. It wraps Apple’s UIAccessibility protocols in Ruby, and provides an accessibility inspector. It has a console for blind developers, since the iOS simulator doesn’t work well with VoiceOver. It also has automated accessibility testing for your views, and the accessibility doctor will help diagnose your problems and tell you how to fix them. You can build accessibility testing into your specs, so you will never break VoiceOver compatibility!
7
+ Motion-accessibility provides the tools needed for sighted and blind iOS
8
+ RubyMotion developers to make their apps more accessible. It wraps Apple’s
9
+ UIAccessibility protocols in Ruby, and provides an accessibility inspector. It
10
+ has a console for blind developers, since the iOS simulator doesn’t work well
11
+ with VoiceOver. It also has automated accessibility testing for your views, and
12
+ the accessibility doctor will help diagnose your problems and tell you how to
13
+ fix them. You can build accessibility testing into your specs, so you will
14
+ never break VoiceOver compatibility!
8
15
 
9
16
  ## Installation
10
17
 
@@ -23,7 +30,9 @@ Or install it yourself as:
23
30
  ## Usage
24
31
  ### The Motion-Accessibility Console
25
32
 
26
- The motion-accessibility console gives you a way to interact with a running application through a purely textual interface. This works well for blind developers and command line users.
33
+ The motion-accessibility console gives you a way to interact with a running
34
+ application through a purely textual interface. This works well for blind
35
+ developers and command line users.
27
36
 
28
37
  #### Enabling the Console
29
38
 
@@ -31,18 +40,15 @@ To enable the console, you can do one of two things. If you would just like to t
31
40
 
32
41
  #### `browse` or `b`
33
42
 
34
- The `browse` or `b` command lets you examine the view hierarchy in a speech-friendly way. This lets you see all the relevant views displayed in your running application. It will detect if the screen has changed and refresh itself automatically.
43
+ The `browse` or `b` command lets you examine the view hierarchy in a
44
+ speech-friendly way. This lets you see all the relevant views displayed in your
45
+ running application. It will detect if the screen has changed and refresh
46
+ itself automatically.
35
47
 
36
48
  The following examples come from the sample app included with motion-accessibility.
37
49
 
38
- ```
39
- (main)> browse
40
- Browsing UIWindow
41
- 1 UIView with 3 subviews
42
- 2 UINavigationBar with 2 subviews
43
- 3 UITabBar with 3 subviews
44
- => nil
45
- ```
50
+ ``` (main)> browse Browsing UIWindow 1 UIView with 3 subviews 2
51
+ UINavigationBar with 2 subviews 3 UITabBar with 3 subviews => nil ```
46
52
 
47
53
  If a view has subviews, you can browse that view.
48
54
 
@@ -56,15 +62,20 @@ Browsing UIView
56
62
  => nil
57
63
  ```
58
64
 
59
- You can return to the top of the view hierarchy by using `:top`. This also refreshes the browser.
65
+ You can return to the top of the view hierarchy by using `:top`. This also
66
+ refreshes the browser.
60
67
 
61
68
  You can refresh a table with `:refresh`.
62
69
 
63
- You may pass the `:scroll` keyword to scroll a UIScrollView or descendants, such as a UITableView. This still has some minor issues .
70
+ You may pass the `:scroll` keyword to scroll a UIScrollView or descendants,
71
+ such as a UITableView. This still has some minor issues .
64
72
 
65
73
  #### `view` or `v`
66
74
 
67
- The `view` or `v` command simply returns the current view. If you have just browsed a view, it will return that. Otherwise, you may specify the view you wish to browse. Note that for all the commands, you may either use its number or accessibility label.
75
+ The `view` or `v` command simply returns the current view. If you have just
76
+ browsed a view, it will return that. Otherwise, you may specify the view you
77
+ wish to browse. Note that for all the commands, you may either use its number
78
+ or accessibility label.
68
79
 
69
80
  ```
70
81
  (main)> v 1
@@ -72,7 +83,9 @@ The `view` or `v` command simply returns the current view. If you have just brow
72
83
  ```
73
84
 
74
85
  #### `touch`
75
- The `touch` command lets you interact with the various controls. It works on all standard UIControls. `touch` can accept an argument depending on the type of control. For example, you can pass a UITextField a string to set its value.
86
+ The `touch` command lets you interact with the various controls. It works on
87
+ all standard UIControls. `touch` can accept an argument depending on the type
88
+ of control. For example, you can pass a UITextField a string to set its value.
76
89
 
77
90
  ```
78
91
  (main)> touch 2,"Motion-accessibility rocks!"
@@ -84,7 +97,9 @@ Browsing UIView
84
97
  => nil
85
98
  ```
86
99
 
87
- UIButtons can take a UIControlEvent, but default to `UIControlEventTouchUpInside`. Note here the use of an accessibility label to reference the view.
100
+ UIButtons can take a UIControlEvent, but default to
101
+ `UIControlEventTouchUpInside`. Note here the use of an accessibility label to
102
+ reference the view.
88
103
 
89
104
  ```
90
105
  (main)> touch "update"
@@ -98,15 +113,13 @@ Browsing UIView
98
113
 
99
114
  ### The Accessibility Inspector
100
115
 
101
- You can easily see the state of any of the following attributes and methods by using the accessibility inspector. Just call `Accessibility.inspect` and pass any object as an argument.
116
+ You can easily see the state of any of the following attributes and methods by
117
+ using the accessibility inspector. Just call `Accessibility.inspect` and pass
118
+ any object as an argument.
102
119
 
103
120
  ```
104
- (main)> label=UILabel.alloc.initWithFrame(CGRect.new([0,0], [100,100]))
105
- => #<UILabel:0x103b8c40>
106
- (main)> label.text="Hello!"
107
- => "Hello!"
108
- (main)> Accessibility.inspect label
109
- #<UILabel:0x103b8c40>
121
+ (main)> A11y.inspect label
122
+ #<UILabel:0xb438140>
110
123
  Accessibility label: Hello!
111
124
  Accessibility hint: nil
112
125
  Accessibility traits: Static text
@@ -117,18 +130,24 @@ Accessibility activation point: x=50.0 y=50.0
117
130
  Accessibility path: nil
118
131
  Accessibility view is modal: false
119
132
  Should group accessibility children: false
133
+ Accessibility elements: nil
120
134
  Accessibility elements hidden: false
121
135
  Is accessibility element: true
136
+ Accessibility custom actions: nil
122
137
  Accessibility identifier: nil
123
138
  Accessible: true
124
139
  => nil
125
140
  ```
126
141
 
127
- By the way, `a11y` stands for `accessibility`, because it has a, then 11 letters, then y. Hence, you can use `A11y.inspect` as a shortcut.
142
+ By the way, `a11y` stands for `accessibility`, because it has a, then 11
143
+ letters, then y. Hence, you can use `A11y.inspect` as a shortcut.
128
144
 
129
145
  ### Automated Accessibility Testing
130
146
 
131
- Below you will find detailed documentation about all of the accessibility protocols. Don’t feel overwhelmed. The accessibility inspector will tell you exactly what you have to do. Let’s start by creating an unlabeled button, the bane of all VOiceOver users.
147
+ Below you will find detailed documentation about all of the accessibility
148
+ protocols. Don’t feel overwhelmed. The accessibility inspector will tell you
149
+ exactly what you have to do. Let’s start by creating an unlabeled button, the
150
+ bane of all VOiceOver users.
132
151
 
133
152
  ```
134
153
  (main)> button=UIButton.new
@@ -157,11 +176,13 @@ Accessible: false
157
176
  This incorporates two features discussed below.
158
177
 
159
178
  #### `accessible?`
160
- Call the `accessible?` predicate on any object to determine its accessibility. Like all predicates it returns true or false. You can include this in your specs. If you build in accessibility testing you will never break accessibility, something even worse than no accessibility at all. For example, if you have a variable `@label` which contains a label, you could write:
161
- ```
162
- @label.should.be.accessible
163
- ```
164
- So simple! This works recursively. Say you run some functional tests on a view controller.
179
+ Call the `accessible?` predicate on any object to determine its accessibility.
180
+ Like all predicates it returns true or false. You can include this in your
181
+ specs. If you build in accessibility testing you will never break
182
+ accessibility, something even worse than no accessibility at all. For example,
183
+ if you have a variable `@label` which contains a label, you could write: ```
184
+ @label.should.be.accessible ``` So simple! This works recursively. Say you run
185
+ some functional tests on a view controller.
165
186
 
166
187
  ```
167
188
  tests Test_Controller
@@ -181,20 +202,30 @@ it “accessible?” do
181
202
  @app.should.be.accessible
182
203
  end
183
204
  ```
184
- You may not want to do this however, because it can get confusing navigating down subview hierarchies, though it will report the path taken. Still, better to do that then nothing at all.
205
+ You may not want to do this however, because it can get confusing navigating
206
+ down subview hierarchies, though it will report the path taken. Still, better
207
+ to do that then nothing at all.
185
208
 
186
209
  #### `Accessibility.doctor`
187
- The accessibility doctor will report on what you have to do. It writes this to the NSLog. If given no arguments it will report on the last object called with the `accessible?` predicate. It returns the object with the problem, or nil if it finds nothing wrong. The accessibility inspector returns this as well. If a spec fails, `accessible?` will call this automatically..
210
+ The accessibility doctor will report on what you have to do. It writes this to
211
+ the NSLog. If given no arguments it will report on the last object called with
212
+ the `accessible?` predicate. It returns the object with the problem, or nil if
213
+ it finds nothing wrong. The accessibility inspector returns this as well. If a
214
+ spec fails, `accessible?` will call this automatically..
188
215
 
189
216
  #### `accessibility_test`
190
- Finally, you can specify which accessibility test applies to an object by setting this value. You may do this in the same way you set other attributes. You can use a setter:
217
+ Finally, you can specify which accessibility test applies to an object by
218
+ setting this value. You may do this in the same way you set other attributes.
219
+ You can use a setter:
191
220
 
192
221
  ```
193
222
  view=UIView.new
194
223
  view.accessibility_test=:UILabel
195
224
  ```
196
225
 
226
+
197
227
  Or you may define it in a class. If you do this make sure that it returns a symbol of the class you want to test against, since it has no error checking unlike the setter.
228
+
198
229
  ```
199
230
  class Custom_View < UIView
200
231
 
@@ -207,15 +238,28 @@ end
207
238
 
208
239
  ### Accessibility vs. Usability
209
240
 
210
- A difference exists between accessibility and usability, though often the two get lumped together under the umbrella of the former. Accessibility refers to whether or not a user can view and interact with something in a meaningful way. In this case, this means making VoiceOver aware of the different elements of your app. Usability gets into more intangible realms, and has to do with whether or not it actually makes sense to a user. In this case this means a blind human using VoiceOver, and only a blind human using VoiceOver can tell you this. A computer can test for accessibility, but only a human can test for usability.
241
+ A difference exists between accessibility and usability, though often the two
242
+ get lumped together under the umbrella of the former. Accessibility refers to
243
+ whether or not a user can view and interact with something in a meaningful way.
244
+ In this case, this means making VoiceOver aware of the different elements of
245
+ your app. Usability gets into more intangible realms, and has to do with
246
+ whether or not it actually makes sense to a user. In this case this means a
247
+ blind human using VoiceOver, and only a blind human using VoiceOver can tell
248
+ you this. A computer can test for accessibility, but only a human can test for
249
+ usability.
211
250
 
212
251
  ### UIAccessibility Informal Protocol
213
252
 
214
- This informal protocol describes how to convey proper information to VoiceOver, the piece of software which allows the blind to read the screen. All of the UIAccessibility attributes now have Ruby-like names. Just like the protocol, these methods belong to the NSObject class, so you can use them anywhere. Usually, you will define them for a UIView.
253
+ This informal protocol describes how to convey proper information to VoiceOver,
254
+ the piece of software which allows the blind to read the screen. All of the
255
+ UIAccessibility attributes now have Ruby-like names. Just like the protocol,
256
+ these methods belong to the NSObject class, so you can use them anywhere.
257
+ Usually, you will define them for a UIView.
215
258
 
216
259
  #### Defining Attributes in a Custom Subclass
217
260
 
218
- You can define these attributes in one of two ways. Firstly you can define a method in a subclass of UIView.
261
+ You can define these attributes in one of two ways. Firstly you can define a
262
+ method in a subclass of UIView.
219
263
 
220
264
  ```
221
265
  class CustomView < UIView
@@ -227,7 +271,9 @@ end
227
271
  end
228
272
  ```
229
273
 
230
- Note that motion-accessibility uses some metaprogramming to accomplish this. It tries to play nicely with other gems. If another gem has already defined the `NSObject.method_added` method, it will alias it and run it before its own.
274
+ Note that motion-accessibility uses some metaprogramming to accomplish this. It
275
+ tries to play nicely with other gems. If another gem has already defined the
276
+ `NSObject.method_added` method, it will alias it and run it before its own.
231
277
 
232
278
  #### Defining Attributes in the Instanciation Code
233
279
 
@@ -240,20 +286,38 @@ view.accessibility_label="Hello."
240
286
 
241
287
  #### `accessibility_label`
242
288
 
243
- What VoiceOver reads. The most important thing to define. Many standard views set the accessibility label automatically. For example, if you set the text of a UILabel, it will also set the accessibility label. However, if you make a custom view you will have to define it. If you set an image for a button, its title will default to the image name. This can have ugly results. Even more annoyingly, if you don't set a label a button will just read as "Button". Make sure to set this.
289
+ What VoiceOver reads. The most important thing to define. Many standard views
290
+ set the accessibility label automatically. For example, if you set the text of
291
+ a UILabel, it will also set the accessibility label. However, if you make a
292
+ custom view you will have to define it. If you set an image for a button, its
293
+ title will default to the image name. This can have ugly results. Even more
294
+ annoyingly, if you don't set a label a button will just read as "Button". Make
295
+ sure to set this.
244
296
 
245
- Labels briefly describe the element. They do not include the control type. They begin with a capitalized word and do not end with a period. Localize them when possible.
297
+ Labels briefly describe the element. They do not include the control type. They
298
+ begin with a capitalized word and do not end with a period. Localize them when
299
+ possible.
246
300
 
247
301
  #### `accessibility_hint`
248
302
 
249
- Hints describe the results of performing an action. Only provide one when not obvious. They briefly describe results. They begin with a verb and omit the subject. They use the third person singular declarative form - Plays music instead of play music. Imagine describing it to a friend. "Tapping the button plays music." They begin with a capitalized word and end with a period. They do not include the action or gesture. They do not include the name or type of the controller or view. Localized.
303
+ Hints describe the results of performing an action. Only provide one when not
304
+ obvious. They briefly describe results. They begin with a verb and omit the
305
+ subject. They use the third person singular declarative form - Plays music
306
+ instead of play music. Imagine describing it to a friend. "Tapping the button
307
+ plays music." They begin with a capitalized word and end with a period. They do
308
+ not include the action or gesture. They do not include the name or type of the
309
+ controller or view. Localized.
250
310
 
251
311
  #### `accessibility_traits`
252
312
 
253
- Traits describe an element's state, behavior, or usage. They tell
254
- VoiceOver how to respond to a view. To combine them, use the single vertical bar `|` binary or operator. Remember to call `super.accessibility_traits` if defining them in a method.
313
+ Traits describe an element's state, behavior, or usage. They tell VoiceOver how
314
+ to respond to a view. To combine them, use the single vertical bar `|` binary
315
+ or operator. Remember to call `super.accessibility_traits` if defining them in
316
+ a method.
255
317
 
256
- The `accessibility_traits=` method also accepts a symbol or array of symbols, and applies the accessibility_traits method to them. For example, if a view displays an image that opens a link, you can do this.
318
+ The `accessibility_traits=` method also accepts a symbol or array of symbols,
319
+ and applies the accessibility_traits method to them. For example, if a view
320
+ displays an image that opens a link, you can do this.
257
321
 
258
322
  ```
259
323
  class ImageLinkView < UIView
@@ -262,9 +326,7 @@ def accessibility_traits
262
326
  super.accessibility_traits|:image.accessibility_trait|:link.accessibility_trait
263
327
  end
264
328
  end
265
- ```
266
-
267
- Or, to set it in an instance of a view you can do this.
329
+ ``uur, to set it in an instance of a view you can do this.
268
330
 
269
331
  ```
270
332
  view=UIView.alloc.init
@@ -282,11 +344,14 @@ The view acts like a search field.
282
344
  ##### :image
283
345
  The view displays an image.
284
346
  ##### :selected
285
- VoiceOver will report the element as selected. For example, a selected row in a table, or segment in a segmented control.
347
+ VoiceOver will report the element as selected. For example, a selected row in a
348
+ table, or segment in a segmented control.
286
349
  ##### :keyboard_key
287
350
  The view behaves like a keyboard key.
288
351
  ##### :header
289
- The view contains a header. VoiceOver will announce this as a heading. VoiceOver allows for navigation between headings. This gives quick access to different sections.
352
+ The view contains a header. VoiceOver will announce this as a heading.
353
+ VoiceOver allows for navigation between headings. This gives quick access to
354
+ different sections.
290
355
  ##### :static_text
291
356
  The view displays static text.
292
357
  ##### :summary_element
@@ -294,13 +359,18 @@ The view provides summary information when the application starts.
294
359
  ##### :plays_sound
295
360
  The view plays its own sound when activated.
296
361
  #### :starts_media_session
297
- Silences VoiceOver during a media session that should not be interrupted. For example, silence VoiceOver speech while the user is recording audio.
362
+ Silences VoiceOver during a media session that should not be interrupted. For
363
+ example, silence VoiceOver speech while the user is recording audio.
298
364
  #### :updates_frequently
299
- Tells VoiceOver to avoid handling continual notifications. Instead it should poll for changes when it needs updated information. You do this with the notifications discussed below.
365
+ Tells VoiceOver to avoid handling continual notifications. Instead it should
366
+ poll for changes when it needs updated information. You do this with the
367
+ notifications discussed below.
300
368
  #### :adjustable
301
- The view has an adjustable value. Also see the `accessibility_increment` and `accessibility_decrement` methods.
369
+ The view has an adjustable value. Also see the `accessibility_increment` and
370
+ `accessibility_decrement` methods.
302
371
  #### :allows_direct_interaction
303
- This tells VoiceOver to allow the user to interact directly with the view. For example, a piano keyboard.
372
+ This tells VoiceOver to allow the user to interact directly with the view. For
373
+ example, a piano keyboard.
304
374
  #### :causes_page_turn
305
375
  Causes an automatic page turn when VoiceOver finishes reading the text within it.
306
376
  #### :not_enabled
@@ -320,19 +390,44 @@ The frame of the accessibility element. This defaults to the frame of the view.
320
390
 
321
391
  #### `accessibility_activation_point`
322
392
 
323
- The point activated when a VoiceOver user activates the view by double tapping it. This defaults to the center of the view. In other words, a VoiceOver can double-tap anywhere on the screen, but it will simulate a sighted user touching the center of the view.
393
+ The point activated when a VoiceOver user activates the view by double tapping
394
+ it. This defaults to the center of the view. In other words, a VoiceOver can
395
+ double-tap anywhere on the screen, but it will simulate a sighted user touching
396
+ the center of the view.
324
397
 
325
398
  #### `accessibility_path`
326
399
 
327
- If nil, the default, VoiceOver uses the `accessibility_frame` to highlight the element. If set, it will use the path. This method accepts a `UIBezierPath`.
400
+ If nil, the default, VoiceOver uses the `accessibility_frame` to highlight the
401
+ element. If set, it will use the path. This method accepts a `UIBezierPath`.
328
402
 
329
403
  #### `accessibility_modal_view?` or `accessibility_view_is_modal`
330
404
 
331
- Ignores elements within views which are siblings of the receiver. If you present a modal view and want VoiceOver to ignore other views on the screen, set this to true.
405
+ Ignores elements within views which are siblings of the receiver. If you
406
+ present a modal view and want VoiceOver to ignore other views on the screen,
407
+ set this to true.
332
408
 
333
409
  #### `group_accessibility_children?` or `should_group_accessibility_children`
334
410
 
335
- VoiceOver gives two ways to browse the screen. The user can drag their finger around the screen and hear the contents. They can also swipe right or left with one finger to hear the next or previous element. When swiping to the next element, VoiceOver reads the elements from left to right, and from top to bottom. Sometimes this can get confusing, depending on the layout of the screen. Setting this to true tells VoiceOver to read the views in the order defined in the subviews array.
411
+ VoiceOver gives two ways to browse the screen. The user can drag their finger
412
+ around the screen and hear the contents. They can also swipe right or left with
413
+ one finger to hear the next or previous element. When swiping to the next
414
+ element, VoiceOver reads the elements from left to right, and from top to
415
+ bottom. Sometimes this can get confusing, depending on the layout of the
416
+ screen. Setting this to true tells VoiceOver to read the views in the order
417
+ defined in the subviews array.
418
+
419
+ #### `accessibility_elements`
420
+
421
+ An array which contains the elements which VoiceOver should access. New in iOS
422
+ 8, this offers a much easier way to create accessibility containers and their
423
+ elements. Simply pass an array with the views.
424
+
425
+ ```
426
+ sample=UIView.new
427
+ label=UILabel.new
428
+ button=UIButton.new
429
+ sample.accessibilitly_elements = [label, button]
430
+ ```
336
431
 
337
432
  #### `accessibility_elements_hidden?` or `accessibility_elements_hidden`
338
433
 
@@ -340,7 +435,66 @@ A boolean value which tells VoiceOver to hide the subviews of this view.
340
435
 
341
436
  #### `accessibility_element?`, or `is_accessibility_element`
342
437
 
343
- Tells VoiceOver whether to regard this as something it can read or not. Standard views have this set to true. Custom views have this set to false.
438
+ Tells VoiceOver whether to regard this as something it can read or not.
439
+ Standard views have this set to true. Custom views have this set to false.
440
+
441
+ #### `accessibility_custom_actions`
442
+
443
+ iOS 8 offers the ability to allow a VoiceOver user to perform custom actions on
444
+ a view. For example, if you have a view which responds to a non-standard wiping
445
+ gesture which a VoiceOver user cannot execute, you can implement these actions
446
+ to allow them to swipe through a list and select one.
447
+
448
+ ##### Creating a Custom Action
449
+
450
+ Custom actions belong to the `A11y::Custom_Action` class. Just call the
451
+ `initWithName:target:selector` method. It takes the following parameters:
452
+ - Name: The name of the action read by VoiceOver
453
+ - Target: The object which receives the message to perform the action, usually
454
+ `self`.
455
+ - Selector: A string containing the name of the method to call when selected
456
+
457
+ ```
458
+ (main)> action=A11y::Custom_Action.alloc.initWithName("Sample Action", target: self, selector: 'sample_action')
459
+ => #<Accessibility::Custom_Action:0xb42e270>
460
+ ```
461
+
462
+ ##### Using a Hash
463
+
464
+ Instead of passing an array of custom actions to
465
+ `accessibility_custom_actions`, you may provide an array of hashes to create
466
+ them.
467
+
468
+ ```
469
+ (main)> test_view=UIView.new
470
+ => #<UIView:0xb435030>
471
+ (main)> test_view.accessibility_custom_actions = [{name: 'Test', target: self, selector: 'test_action'}, {name: 'Another test', target: self, selector: 'another_test_action'}]
472
+ => [#<Accessibility::Custom_Action:0x10c78d90>, #<Accessibility::Custom_Action:0x10c68f10>]
473
+ ```
474
+
475
+ You can then see them in the inspector.
476
+
477
+ ```
478
+ (main)> A11y.inspect test_view
479
+ #<UIView:0xb435030>
480
+ Accessibility label: nil
481
+ Accessibility hint: nil
482
+ Accessibility traits: None
483
+ Accessibility value: nil
484
+ Accessibility language: nil
485
+ Accessibility frame: x=0.0 y=0.0 width=0.0 height=0.0
486
+ Accessibility activation point: x=0.0 y=0.0
487
+ Accessibility path: nil
488
+ Accessibility view is modal: false
489
+ Should group accessibility children: false
490
+ Accessibility elements: nil
491
+ Accessibility elements hidden: false
492
+ Is accessibility element: false
493
+ Accessibility custom actions: ["Test", "Another test"]
494
+ Accessibility identifier: nil
495
+ Accessible: true
496
+ => nil
497
+ ```
344
498
 
345
499
  #### `accessibility_identifier`
346
500
 
@@ -348,7 +502,8 @@ A unique identifier if you don't want to define the accessibility label.
348
502
 
349
503
  ### UIPickerView
350
504
 
351
- If desired, you can use these methods to make your picker views more accessible. You only need to do this if the picker contains non-standard views.
505
+ If desired, you can use these methods to make your picker views more
506
+ accessible. You only need to do this if the picker contains non-standard views.
352
507
  #### `accessibility_label_for_component`
353
508
  Accepts an integer and returns the accessibility label for the component.
354
509
  #### `accessibility_hint_for_component `
@@ -356,23 +511,33 @@ Accepts an integer and returns the accessibility hint for the component.
356
511
 
357
512
  ### UIAccessibility Actions
358
513
 
359
- These methods trigger when the VoiceOver user performs specific actions. You can implement then in a UIView or an accessibility element.
514
+ These methods trigger when the VoiceOver user performs specific actions. You
515
+ can implement then in a UIView or an accessibility element.
360
516
 
361
517
  #### `accessibility_activate`
362
518
 
363
- New in iOS 7, this method performs a custom action when a VoiceOver double-taps the view. You can use this if the view uses a custom gesture, for example. It returns true or false depending on the success of the action.
519
+ New in iOS 7, this method performs a custom action when a VoiceOver double-taps
520
+ the view. You can use this if the view uses a custom gesture, for example. It
521
+ returns true or false depending on the success of the action.
364
522
 
365
523
  #### `accessibility_perform_escape`
366
524
 
367
- VoiceOver has a special two-finger scrub gesture designed to act as a back button. The standard back button of a UINavigationController implements this method. It dismisses a modal view, and returns the success or failure of the action. For example, you could use this to dismiss a popover.
525
+ VoiceOver has a special two-finger scrub gesture designed to act as a back
526
+ button. The standard back button of a UINavigationController implements this
527
+ method. It dismisses a modal view, and returns the success or failure of the
528
+ action. For example, you could use this to dismiss a popover.
368
529
 
369
530
  #### `Accessibility_perform_magic_tap`
370
531
 
371
- VoiceOver has a special two-finger double-tap. This method should toggle the most important state of the program. For example, if a song plays it will pause and resume the song. If on a telephone call, doing a magic tap will end it.
532
+ VoiceOver has a special two-finger double-tap. This method should toggle the
533
+ most important state of the program. For example, if a song plays it will pause
534
+ and resume the song. If on a telephone call, doing a magic tap will end it.
372
535
 
373
536
  #### `accessibility_scroll`
374
537
 
375
- VoiceOver uses three-finger swipes to scroll the screen. These gestures will trigger this method. It accepts a scroll direction as a parameter. If the scrolling succeeds, it should return true and post a :scroll notification.
538
+ VoiceOver uses three-finger swipes to scroll the screen. These gestures will
539
+ trigger this method. It accepts a scroll direction as a parameter. If the
540
+ scrolling succeeds, it should return true and post a :scroll notification.
376
541
 
377
542
  #### Scroll Directions
378
543
 
@@ -387,7 +552,8 @@ VoiceOver uses three-finger swipes to scroll the screen. These gestures will tri
387
552
 
388
553
  #### `accessibility_increment`
389
554
 
390
- Increments the value of the accessibility element. Make sure to have the :adjustable accessibility trait set for this to work.
555
+ Increments the value of the accessibility element. Make sure to have the
556
+ :adjustable accessibility trait set for this to work.
391
557
 
392
558
  #### `accessibility_decrement`
393
559
 
@@ -395,7 +561,13 @@ Decrements the value of the accessibility element. Make sure to have the :adjust
395
561
 
396
562
  ### Accessibility::Element
397
563
 
398
- If you have something in your view that does not inherit from UIView or UIControl and you want to make it accessible, you need to define it as an accessibility element. Accessibility elements belong to an accessibility container, in other words the view which contains them. To create one, just call `Accessibility::Element.init_with_accessibility_container` with the container, usually self. Like a UIView, an accessibility element has attributes, and you get and set them in exactly the same way.
564
+ If you have something in your view that does not inherit from UIView or
565
+ UIControl and you want to make it accessible, you need to define it as an
566
+ accessibility element. Accessibility elements belong to an accessibility
567
+ container, in other words the view which contains them. To create one, just
568
+ call `Accessibility::Element.init_with_accessibility_container` with the
569
+ container, usually self. Like a UIView, an accessibility element has
570
+ attributes, and you get and set them in exactly the same way.
399
571
 
400
572
  ```
401
573
  class CustomView < UIView
@@ -439,22 +611,31 @@ The value of the element, if applicable.
439
611
 
440
612
  #### `is_accessibility_element` or `accessibility_element?`
441
613
 
442
- Returns true if VoiceOver should consider this an accessibility element. Note that you can only use `is_accessibility_element?=` as a setter.
614
+ Returns true if VoiceOver should consider this an accessibility element. Note
615
+ that you can only use `is_accessibility_element?=` as a setter.
443
616
 
444
617
  ### UIAccessibilityContainer Informal Protocol
445
618
 
446
- The UIAccessibility Container informal protocol allows VoiceOver to handle a custom view which acts like a container. It tells VoiceOver how to read the subviews in the proper order. It contains accessibility elements. Just implement these methods in a subclass of UIView.
619
+ The UIAccessibility Container informal protocol allows VoiceOver to handle a
620
+ custom view which acts like a container. It tells VoiceOver how to read the
621
+ subviews in the proper order. It contains accessibility elements. Just
622
+ implement these methods in a subclass of UIView.
447
623
 
448
624
  #### `accessibility_element_at_index`
449
625
  Accepts an integer and returns the accessibility element. You can use the standard `Array#[]` method for this.
450
626
  #### `accessibility_element_count`
451
627
  Returns the number of accessible elements. You can use `Array#length` for this.
452
628
  #### `index_of_accessibility_element`
453
- Accepts an accessibility element and returns its index as an integer. You can use the `Array#index` method for this.
629
+ Accepts an accessibility element and returns its index as an integer. You can
630
+ use the `Array#index` method for this.
631
+ #### `accessibility_element_container?`
632
+ Returns true if the object behaves like a container.
454
633
 
455
634
  ### UIAccessibilityFocus Informal Protocol
456
635
 
457
- This protocol lets you take actions if a view gains or loses VoiceOver's focus. Note that if you use these in an Accessibility::Element that you can leave off the `accessibility_element_` prefix.
636
+ This protocol lets you take actions if a view gains or loses VoiceOver's focus.
637
+ Note that if you use these in an Accessibility::Element that you can leave off
638
+ the `accessibility_element_` prefix.
458
639
  #### `accessibility_element_did_become_focused`
459
640
  Triggered when the accessibility element becomes focused by VoiceOver.
460
641
  #### `accessibility_element_did_lose_focus`
@@ -475,7 +656,12 @@ Accepts a CGPoint and returns the line number of the text to read.
475
656
 
476
657
  ### Notifications
477
658
 
478
- The UIAccessibility notifications can either come from UIKit or from applications. You can observe them with the standard notification center. You can post them with `Accessibility.post_notification`. It takes one of the following symbols as a parameter. Many notifications have additional parameters as well. Motion-Accessibility adds an accessibility_notification method to the Symbol class.
659
+ The UIAccessibility notifications can either come from UIKit or from
660
+ applications. You can observe them with the standard notification center. You
661
+ can post them with `Accessibility.post_notification`. It takes one of the
662
+ following symbols as a parameter. Many notifications have additional parameters
663
+ as well. Motion-Accessibility adds an accessibility_notification method to the
664
+ Symbol class.
479
665
 
480
666
  For example, if a view controller removes a subview and adds another, you will want to post the screen changed notification. You can do this with
481
667
 
@@ -486,15 +672,23 @@ Accessibility.post_notification(:screen_changed)
486
672
  Much easier, don't you think?
487
673
 
488
674
  #### :layout_changed
489
- Your application should post this notification when a part of the screen's layout changes. It has one parameter. You can provide a string which VoiceOver should speak. You can also provide an accessibility element, such as a UIView, and VoiceOver will move there.
675
+ Your application should post this notification when a part of the screen's
676
+ layout changes. It has one parameter. You can provide a string which VoiceOver
677
+ should speak. You can also provide an accessibility element, such as a UIView,
678
+ and VoiceOver will move there.
490
679
  #### :screen_changed
491
- Your application should post this notification when a major part of the screen changes. It has the same parameter as `:layout_changed`.
680
+ Your application should post this notification when a major part of the screen
681
+ changes. It has the same parameter as `:layout_changed`.
492
682
  #### :page_scrolled
493
- Post this notification after calling `Accessibility.scroll`. Include a string which describes the scrolling action, for example "Page 3 of 10".
683
+ Post this notification after calling `Accessibility.scroll`. Include a string
684
+ which describes the scrolling action, for example "Page 3 of 10".
494
685
  #### :announcement
495
- Post this notification to make VoiceOver output something. Just include the string.
686
+ Post this notification to make VoiceOver output something. Just include the
687
+ string.
496
688
  #### :announcement_did_finish
497
- UIKit posts this announcement when VoiceOver finishes announcing something. It accepts a dictionary with the following keys as a parameter. Use the zoom_type method on these symbols.
689
+ UIKit posts this announcement when VoiceOver finishes announcing something. It
690
+ accepts a dictionary with the following keys as a parameter. Use the zoom_type
691
+ method on these symbols.
498
692
  - :announcement_key_string_value
499
693
  - :announcement_key_was_successful
500
694
  #### :closed_captioning
@@ -507,26 +701,65 @@ UIKit posts this when the user toggles inverted colors.
507
701
  UIKit posts this when the user toggles mono audio.
508
702
  #### :voiceover
509
703
  UIKit posts this when the user toggles VoiceOver.
704
+ #### :bold_text
705
+ UIKit posts this when the user toggles the Bold Text accessibility setting.
706
+ #### :darker_colors
707
+ UIKit posts this when the user toggles the Darker Colors accessibility setting.
708
+ #### :grayscale
709
+ Posted when the user toggles the Grayscale accessibility setting
710
+ #### :reduce_motion
711
+ Posted when the user toggles the Reduce Motion accessibility seting. This can
712
+ help users who feel dizzy by all the fancy animations.
713
+ #### :reduce_transparency
714
+ Posted when the user toggles the Reduce Transparency accessibility setting.
715
+ #### :speak_selection
716
+ Posted when the user toggles the Speak Selection setting located in Accessibility -> Speech
717
+ #### :speak_screen
718
+ Posted when the user toggles the Speak Screen setting located under Accessibility -> Speech
719
+ #### :switch_control
720
+ Posted when the user toggles use of a switch control
721
+ #### :switch_control_identifier
722
+ Contains the unique identifier of the switch control
723
+ #### :resume_assistive_technology
724
+ Post this notification to resume VoiceOver or other assistive technology
725
+
726
+ #### :pause_assistive_technology
727
+ Post this notification to pause VoiceOver or other assistive technology
510
728
 
511
729
  ### Determining the Status of Accessibility Components
512
- You can use these handy methods to determine the status of different accessibility components. They take no parameters and return true or false.
730
+ You can use these handy methods to determine the status of different
731
+ accessibility components. They take no parameters and return true or false.
513
732
 
514
733
  - `Accessibility.voiceover_running?`
515
734
  - `Accessibility.closed_captioning_enabled?`
516
735
  - `Accessibility.guided_access_enabled?`
517
736
  - `Accessibility.invert_colors_enabled?`
518
737
  - `Accessibility.mono_audio_enabled?`
738
+ - `Accessibility.darker_system_colors_enabled?`
739
+ - `Accessibility.bold_text_enabled?`
740
+ - `Accessibility.grayscale_enabled?`
741
+ - `Accessibility.reduce_motion_enabled?`
742
+ - `Accessibility.reduce_transparency_enabled?`
743
+
744
+ - `Accessibility.speak_selection_enabled?`
745
+ - `Accessibility.speak_screen_enabled?`
746
+ - `Accessibility.switch_control_running?`
747
+
519
748
 
520
- Additionally, these two methods relate to the Zoom screen magnification software.
749
+ Additionally, these two methods relate to the Zoom screen magnification
750
+ software.
521
751
 
522
752
  #### `Accessibility.zoom_focused_changed`
523
- This notifies Zoom that an app's focus has changed. It takes a zoom type described above, a frame, and the view containing the frame.
753
+ This notifies Zoom that an app's focus has changed. It takes a zoom type
754
+ described above, a frame, and the view containing the frame.
524
755
  #### `Accessibility.register_gesture_conflicts_with_zoom`
525
- This issues a dialog to the user when a three-fingered gesture conflicts with Zoom. It lets them choose to disable Zoom or continue.
756
+ This issues a dialog to the user when a three-fingered gesture conflicts with
757
+ Zoom. It lets them choose to disable Zoom or continue.
526
758
 
527
759
  ### Speech Attributes
528
760
 
529
- iOS 7 adds some speech attributes to use in attributed strings. To get them, just call the `speech_attribute` method on the following symbols.
761
+ iOS 7 adds some speech attributes to use in attributed strings. To get them,
762
+ just call the `speech_attribute` method on the following symbols.
530
763
  - `:punctuation`
531
764
  - `:language`
532
765
  - `:pitch`
@@ -542,4 +775,4 @@ iOS 7 adds some speech attributes to use in attributed strings. To get them, jus
542
775
 
543
776
  ## A Special Offer for You
544
777
 
545
- I do [freelance accessibility consulting.](austinseraphin.com) If you use my gem I will give you a discount. Contact me for more information.
778
+ I do [freelance accessibility consulting.](austinseraphin.com) If you use my gem I will give you a discount. Contact me for more information.
@@ -6,3 +6,4 @@ lib_dir_path = File.dirname(File.expand_path(__FILE__))
6
6
  Motion::Project::App.setup do |app|
7
7
  app.files.unshift(Dir.glob(File.join(lib_dir_path, "motion-accessibility-console/**/*.rb")))
8
8
  end
9
+
@@ -1,4 +1,4 @@
1
- class Accessibility
1
+ module Accessibility
2
2
 
3
3
  Data={}
4
4
 
@@ -25,6 +25,8 @@ Attributes = {
25
25
  :should_group_accessibility_children => :shouldGroupAccessibilityChildren,
26
26
  :group_accessibility_children? => :shouldGroupAccessibilityChildren,
27
27
  :should_group_accessibility_children= => :setShouldGroupAccessibilityChildren,
28
+ :accessibility_elements => :accessibilityElements,
29
+ :accessibility_elements= => :setAccessibilityElements,
28
30
  :accessibility_elements_hidden => :accessibilityElementsHidden,
29
31
  :accessibility_elements_hidden? => :accessibilityElementsHidden,
30
32
  :accessibility_elements_hidden= => :setAccessibilityElementsHidden,
@@ -35,6 +37,8 @@ Attributes = {
35
37
  :accessibility_element? => :isAccessibilityElement,
36
38
  :is_accessibility_element => :isAccessibilityElement,
37
39
  :is_accessibility_element= => :setIsAccessibilityElement,
40
+ :accessibility_custom_actions => :accessibilityCustomActions,
41
+ :accessibility_custom_actions= => :setAccessibilityCustomActions,
38
42
  :accessibility_identifier => :accessibilityIdentifier,
39
43
  :accessibility_identifier= => :setAccessibilityIdentifier
40
44
  }
@@ -131,6 +135,23 @@ Notifications = {
131
135
  :voiceover => UIAccessibilityVoiceOverStatusChanged
132
136
  }
133
137
 
138
+ if UIDevice.currentDevice.systemVersion.to_f>=8.0
139
+ IOS8_Notifications = {
140
+ :bold_text => UIAccessibilityBoldTextStatusDidChangeNotification,
141
+ :darker_colors => UIAccessibilityDarkerSystemColorsStatusDidChangeNotification,
142
+ :grayscale => UIAccessibilityGrayscaleStatusDidChangeNotification,
143
+ :reduce_motion => UIAccessibilityReduceMotionStatusDidChangeNotification,
144
+ :reduce_transparency => UIAccessibilityReduceTransparencyStatusDidChangeNotification,
145
+ :speak_screen => UIAccessibilitySpeakScreenStatusDidChangeNotification,
146
+ :speak_selection => UIAccessibilitySpeakSelectionStatusDidChangeNotification,
147
+ :switch_control => UIAccessibilitySwitchControlStatusDidChangeNotification,
148
+ :switch_control_identifier => UIAccessibilityNotificationSwitchControlIdentifier,
149
+ :pause_assistive_technology => UIAccessibilityPauseAssistiveTechnologyNotification,
150
+ :resume_assistive_technology => UIAccessibilityResumeAssistiveTechnologyNotification
151
+ }
152
+ IOS8_Notifications.each {|ruby,ios| Notifications[ruby]=ios}
153
+ end
154
+
134
155
  def Accessibility.post_notification(notification, *args)
135
156
  if(notification.kind_of?(Fixnum))
136
157
  UIAccessibilityPostNotification(notification, *args)
@@ -169,7 +190,9 @@ Attribute_Types = {
169
190
  :accessibilityViewIsModal=>:boolean,
170
191
  :shouldGroupAccessibilityChildren=>:boolean,
171
192
  :accessibilityElementsHidden=>:boolean,
172
- :isAccessibilityElement=>:boolean
193
+ :isAccessibilityElement=>:boolean,
194
+ :accessibilityElements => :accessibility_elements,
195
+ :accessibilityCustomActions => :accessibility_custom_actions
173
196
  }
174
197
 
175
198
  Default_Type_Values = {
@@ -177,7 +200,9 @@ Default_Type_Values = {
177
200
  :boolean => true,
178
201
  :fixnum => 23,
179
202
  :cgrect=>CGRectMake(0,0,100,100),
180
- :cgpoint=>CGPointMake(100,100)
203
+ :cgpoint=>CGPointMake(100,100),
204
+ :accessibility_elements => [UIView.new],
205
+ :accessibility_custom_actions => [UIAccessibilityCustomAction.alloc.initWithName("Test", target: self, selector: 'test')]
181
206
  }
182
207
 
183
208
  def self.attribute_type(attribute)
@@ -253,4 +278,5 @@ end
253
278
 
254
279
  end
255
280
 
256
- A11y=Accessibility unless defined?(A11y)
281
+ A11y=Accessibility unless defined? A11y
282
+ A11y::Custom_Action = UIAccessibilityCustomAction unless defined? A11y::Custom_Action
@@ -1,9 +1,13 @@
1
1
  class UIAccessibilityElement
2
2
 
3
- def self.init_with_accessibility_container(container)
3
+ def init_with_accessibility_container(container)
4
4
  UIAccessibilityElement.alloc.initWithAccessibilityContainer(container)
5
5
  end
6
6
 
7
+ def inspect
8
+ self.accessibility_label
9
+ end
10
+
7
11
  Accessibility::Element_Attributes.each do |ruby,ios|
8
12
  if ruby=~/=$/
9
13
  define_method(ruby) {|value| self.send(ios,value)}
@@ -24,12 +28,12 @@ def traits=(traits)
24
28
  end
25
29
 
26
30
  if self.respond_to?(:method_added)
27
- alias :method_added_accessibility :method_added
31
+ alias :method_added_accessibility_element :method_added
28
32
  end
29
33
 
30
34
  def self.method_added(name)
31
35
  if self.respond_to?(:method_added_accessibility)
32
- method_added_accessibility(name)
36
+ method_added_accessibility_element(name)
33
37
  end
34
38
  return if name=~/=$/
35
39
  attributes=Accessibility::Element_Attributes
@@ -48,18 +52,18 @@ define_method(ruby) { self.send(ios)}
48
52
  end
49
53
  end
50
54
 
51
- def self.container?(obj)
52
- !obj.accessibility_element_at_index(0).nil?
53
- end
54
-
55
55
  end
56
56
 
57
- Accessibility::Element=UIAccessibilityElement
57
+ Accessibility::Element=UIAccessibilityElement unless defined? Accessibility::Element
58
58
 
59
59
  class NSObject
60
60
 
61
+ def accessibility_element_container?
62
+ self.accessibility_element_at_index(0)?true:false
63
+ end
64
+
61
65
  def each_accessibility_element
62
- return unless A11y::Element.container?(self)
66
+ return unless self.accessibility_element_container?
63
67
  self.accessibility_element_count.times {|n| yield(self.accessibility_element_at_index(n))}
64
68
  end
65
69
 
@@ -18,7 +18,7 @@ self.inspect_accessibility_attribute(obj,ios)
18
18
  displayed<<ios
19
19
  end
20
20
  puts "Accessibility test: #{obj.accessibility_test}" if obj.accessibility_test
21
- puts "Accessibility container: #{obj.accessibility_element_count} elements" if A11y::Element.container?(obj)
21
+ puts "Accessibility container: #{obj.accessibility_element_count} elements" if obj.accessibility_element_container?
22
22
  puts "Accessible: #{obj.accessible?}"
23
23
  A11y.doctor
24
24
  end
@@ -40,6 +40,8 @@ value=false if value==0||value.nil?
40
40
  when :cgrect then value="x=#{value.origin.x.round(1)} y=#{value.origin.y.round(1)} width=#{value.size.width.round(1)} height=#{value.size.height.round(1)}"
41
41
  when :cgpoint then value="x=#{value.x.round(1)} y=#{value.y.round(1)}"
42
42
  when :uibezierpath then value="x=#{value.bounds.origin.x.round(1)} y=#{value.bounds.origin.y.round(1)} width=#{value.bounds.size.width.round(1)} height=#{value.bounds.size.height.round(1)}"
43
+ when :accessibility_elements then value=value.map {|v| v.accessibility_label}
44
+ when :accessibility_custom_actions then value=value.map {|a| a.name}
43
45
  end
44
46
  else
45
47
  value="nil" if value.nil?
@@ -2,6 +2,7 @@ module Accessibility
2
2
  module Console
3
3
 
4
4
  $browser_path=[]
5
+ $browser_last=nil
5
6
  Update_Delay=1.0
6
7
 
7
8
  def self.touchable_type(view)
@@ -9,6 +10,9 @@ control=view.class
9
10
  until A11y::Touchable_Types.member?(control.to_s)||control.nil?
10
11
  control=control.superclass
11
12
  end
13
+ if control.class==UITableViewCell
14
+ control=nil unless controll.respond_to?("tableView:didSelectRowAtIndexPath")
15
+ end
12
16
  control
13
17
  end
14
18
 
@@ -78,6 +82,7 @@ end
78
82
  A11y::Console.init unless A11y::Data[:refresh]
79
83
  $browser_current=found
80
84
  $browser_path<<found
85
+ $browser_last=request
81
86
  end
82
87
  elsif request.respond_to?(:view)&&request.respond_to?(:subviews)
83
88
  A11y::Console.init(request)
@@ -105,11 +110,20 @@ def view(request=nil)
105
110
  A11y::Console.init unless A11y::Data[:refresh]
106
111
  $browser_current=$browser_tree unless $browser_current
107
112
  $browser_cursor=$browser_tree unless $browser_cursor
108
- return $browser_cursor.view unless request
113
+ result=nil
114
+ if request
109
115
  result=$browser_current.find(request)
110
116
  raise "Unknown view" unless result
111
117
  $browser_cursor=result
112
- result.view
118
+ result=result.view
119
+ else
120
+ result=$browser_cursor.view
121
+ result
122
+ end
123
+ if result.class==UITableViewCellAccessibilityElement
124
+ result=result.tableViewCell
125
+ end
126
+ result
113
127
  end
114
128
 
115
129
  module_function :browse, :view
@@ -1,13 +1,16 @@
1
1
  module Accessibility
2
2
  module Console
3
3
 
4
- def self.touch(view, arg=nil, options={})
4
+ def self.touch(request, arg=nil, options={})
5
5
  self.start_refreshing
6
6
  $browser_current=$browser_tree unless $browser_current
7
+ view=nil
7
8
  unless RUBYMOTION_ENV=='test'
8
- found=$browser_current.find(view)
9
+ found=$browser_current.find(request)
9
10
  raise "Could not find the view" unless found
10
11
  view=found.view
12
+ else
13
+ view=request
11
14
  end
12
15
  control=A11y::Console.touchable_type(view)
13
16
  raise "I don't know how to touch a #{view.class}" if control.nil?
@@ -39,14 +42,29 @@ when "UISwitch"
39
42
  arg||=!view.arg
40
43
  view.on=arg
41
44
  when "UITableViewCell"
45
+ raise "You cannot touch cells in this table." unless sv.delegate.respond_to?("tableView:didSelectRowAtIndexPath")
42
46
  raise "Could not get the UITableView" unless sv.kind_of?(UITableView)
43
- index=options[:index]||sv.indexPathForCell(view)
47
+ if sv.respond_to?(:numberOfSections)
48
+ sections=sv.numberOfSections
49
+ else
50
+ sections=1
51
+ end
52
+ if sections>1
53
+ index=options[:index]||NSIndexPath.indexPathForRow(request-1, inSection: $browser_last-1)
54
+ else
55
+ index=options[:index]||NSIndexPath.indexPathForRow(request-1, inSection: 0)
56
+ end
44
57
  raise "Could not get the index" unless index
45
- sv.delegate.tableView(self, didSelectRowAtIndexPath: index)
58
+ sv.delegate.tableView(sv.delegate, didSelectRowAtIndexPath: index)
46
59
  when "UITableViewCellAccessibilityElement"
47
- raise "Could not get the UITableView" unless sv.kind_of?(UITableView)
48
- index=options[:index]||sv.indexPathForCell(view.tableViewCell)
60
+ raise "You cannot touch cells in this table." unless view.container.delegate.respond_to?("tableView:didSelectRowAtIndexPath")
61
+ if options[:index]
62
+ index=options[:index]
63
+ else
64
+ raise "Invalid number" if request>view.container.delegate.accessibility_element_count
65
+ index=view.container.indexPathForCell(view.tableViewCell)
49
66
  raise "Could not get the index" unless index
67
+ end
50
68
  view.container.delegate.tableView(view.container, didSelectRowAtIndexPath: index)
51
69
  when "UINavigationItemButtonView"
52
70
  view.superview.delegate.popViewControllerAnimated(true)
@@ -18,14 +18,29 @@ self.subviews.each {|subview| other.subviews<<subview.clone}
18
18
  other
19
19
  end
20
20
 
21
+ def self.container_equals(v1, v2, depth=0)
22
+ return false unless v1==v2
23
+ return false unless v1.accessibility_element_count==v2.accessibility_element_count
24
+ if v1.accessibility_element_container?
25
+ v1.accessibility_element_count.times do |element_index|
26
+ return false unless self.container_equals(v1.accessibility_element_at_index(element_index), v2.accessibility_element_at_index(element_index), depth+1)
27
+ end
28
+ end
29
+ true
30
+ end
31
+
21
32
  def ==(other)
22
33
  return false if other.nil?
23
34
  return false if self.superview&&other.superview&&self.superview.view!=other.superview.view
35
+ if self.view.accessibility_element_container?
36
+ A11y::Console::Tree.container_equals(self.view, other.view)
37
+ else
24
38
  return false unless self.view==other.view
25
39
  return false unless self.subviews.size==other.subviews.size
26
40
  self.subviews.each_index {|index| return false unless self.subviews[index]==other.subviews[index]}
27
41
  return true
28
42
  end
43
+ end
29
44
 
30
45
  def [](n)
31
46
  a=[@view]
@@ -64,6 +79,8 @@ if @view.class==UITableViewCell
64
79
  name=view.text
65
80
  elsif @view.class==UITableViewCellAccessibilityElement
66
81
  name=view.tableViewCell.text
82
+ elsif view.respond_to?(:text)
83
+ name=view.text
67
84
  elsif @view.class==UITextField
68
85
  name=@view.text
69
86
  else
@@ -108,7 +125,20 @@ A11y::Test::Data[:quiet]=true
108
125
  tree=self.new
109
126
  view=UIApplication.sharedApplication.keyWindow if view.nil?
110
127
  subviews=[]
111
- if A11y::Element.container?(view)
128
+ if view.respond_to?(:numberOfSections)
129
+ view.numberOfSections.times do |section_number|
130
+ section=self.new(view: view, superview: tree)
131
+ view.numberOfRowsInSection(section_number).times do |row_number|
132
+ index_path=NSIndexPath.indexPathForRow(row_number, inSection: section_number)
133
+ cell=view.delegate.tableView(view, cellForRowAtIndexPath: index_path)
134
+ raise "Could not get the cell" unless cell
135
+ cell_node=self.build(cell, section)
136
+ section.subviews<<cell_node
137
+ end
138
+ subviews<<section
139
+ end
140
+ subviews=subviews.first.subviews if subviews.size==1
141
+ elsif view.accessibility_element_container?
112
142
  view.each_accessibility_element do |element|
113
143
  subview_tree=self.build(element, tree)
114
144
  subviews<<subview_tree
@@ -50,6 +50,22 @@ self.accessibilityTraits=bits
50
50
  self
51
51
  end
52
52
 
53
+ def accessibility_custom_actions=(actions)
54
+ raise "You must pass an array to custom_accessibility_actions=" unless actions.kind_of?(Array)
55
+ actions.map! do |action|
56
+ if action.kind_of?(A11y::Custom_Action)
57
+ action
58
+ elsif action.kind_of?(Hash)
59
+ %w[name target selector].each {|key| raise "You must provide the #{key}" unless action[key.to_sym]}
60
+ UIAccessibilityCustomAction.alloc.initWithName(action[:name], target: action[:target], selector: action[:selector])
61
+ else
62
+ raise "Unknown custom accessibility action #{action.inspect}"
63
+ end
64
+ end
65
+ self.accessibilityCustomActions=actions
66
+ self
67
+ end
68
+
53
69
  if self.respond_to?(:method_added)
54
70
  class << self
55
71
  alias :method_added_motion_accessibility :method_added
@@ -26,5 +26,32 @@ def registered_gesture_conflict_with_zoom
26
26
  UIAccessibilityRegisterGestureConflictWithZoom()
27
27
  end
28
28
 
29
+ if UIDevice.currentDevice.systemVersion.to_f>=8.0
30
+ def darker_system_colors_enabled?
31
+ UIAccessibilityDarkerSystemColorsEnabled()
32
+ end
33
+ def bold_text_enabled?
34
+ UIAccessibilityIsBoldTextEnabled()
35
+ end
36
+ def grayscale_enabled?
37
+ UIAccessibilityIsGrayscaleEnabled()
38
+ end
39
+ def reduce_motion_enabled?
40
+ UIAccessibilityIsReduceMotionEnabled()
41
+ end
42
+ def reduce_transparency_enabled?
43
+ UIAccessibilityIsReduceTransparencyEnabled()
44
+ end
45
+ def speak_screen_enabled?
46
+ UIAccessibilityIsSpeakScreenEnabled()
47
+ end
48
+ def speak_selection_enabled?
49
+ UIAccessibilityIsSpeakSelectionEnabled()
50
+ end
51
+ def switch_control_running?
52
+ UIAccessibilityIsSwitchControlRunning()
53
+ end
54
+ end
55
+
29
56
  end
30
57
  end
data/lib/project/test.rb CHANGED
@@ -8,6 +8,13 @@ quiet: false,
8
8
  debug: false
9
9
  }
10
10
 
11
+ def self.quiet
12
+ Data[:quiet]
13
+ end
14
+ def self.quiet=(q)
15
+ Data[:quiet]=q
16
+ end
17
+
11
18
  Options = {
12
19
  recurse: true
13
20
  }
@@ -256,6 +263,48 @@ quiet: false,
256
263
  }
257
264
  }
258
265
 
266
+ if UIDevice.currentDevice.systemVersion.to_f>=8.0
267
+ Tests[:UIActionSheet] = {
268
+ accessibility_label: nil,
269
+ is_accessibility_element: false,
270
+ accessibility_view_is_modal: false
271
+ }
272
+ Tests[:UINavigationTransitionView] = {
273
+ accessibility_label: nil,
274
+ should_group_accessibility_children: :ignore,
275
+ is_accessibility_element: false
276
+ }
277
+ Tests[:UIPageControl] = {
278
+ accessibility_label: nil,
279
+ is_accessibility_element: false,
280
+ accessibility_value: [String, "You must set the accessibility_value to something meaningful, for example 'Page 1 of 1'"],
281
+ accessibility_traits: UIAccessibilityTraitUpdatesFrequently|UIAccessibilityTraitAdjustable
282
+ }
283
+ Tests[:UISlider] = {
284
+ accessibility_label: nil,
285
+ accessibility_value: String,
286
+ accessibility_traits: UIAccessibilityTraitAdjustable,
287
+ is_accessibility_element: false,
288
+ options: {recurse: false}
289
+ }
290
+ Tests[:UITableView] = {
291
+ accessibility_label: nil,
292
+ accessibility_traits: ->(t){A11y::Test.nonstandard(t)},
293
+ should_group_accessibility_children: true,
294
+ is_accessibility_element: false
295
+ }
296
+ Tests[:UITableViewCell] = {
297
+ accessibility_label: :ignore,
298
+ accessibility_value: :ignore,
299
+ should_group_accessibility_children: true,
300
+ is_accessibility_element: false,
301
+ options: {
302
+ recurse: false,
303
+ test: :tableViewCell
304
+ }
305
+ }
306
+ end
307
+
259
308
  def self.debug
260
309
  Data[:debug]
261
310
  end
@@ -411,7 +460,7 @@ after=tests[:options][:test]
411
460
  result=result&&this_result
412
461
  Data[:depth]=Data[:depth]-1
413
462
  end
414
- if result&&A11y::Element.container?(obj)
463
+ if result&&obj.accessibility_element_container?
415
464
  result=result&&self.container(obj)
416
465
  end
417
466
  if result&&tests[:options][:recurse]&&obj.respond_to?(:subviews)&&obj.subviews
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion-accessibility
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.3
4
+ version: '3.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Austin Seraphin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-24 00:00:00.000000000 Z
11
+ date: 2014-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake