motion-accessibility 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +339 -0
- data/lib/motion-accessibility.rb +8 -0
- data/lib/project/constants.rb +166 -0
- data/lib/project/element.rb +59 -0
- data/lib/project/motion-accessibility.rb +6 -0
- data/lib/project/object.rb +60 -0
- data/lib/project/picker.rb +27 -0
- data/lib/project/status.rb +30 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 001fe9a43e5cec6cc4e07c36881780450da14db4
|
4
|
+
data.tar.gz: 1ba2bedc38da07bb1cbd64d3534b1bcd3eb6f8b4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e1d91838885bd6ff9df11b592afd89332da2f567ec700a6a64ca0923e991f81d4e5140c3994f2c8475e355bdf2fabaeeef0e42006e432a9902705914203f7d66
|
7
|
+
data.tar.gz: 5fcb8c76f890238e5c7025fb36037b55934fffccb9567ed799ecb17353706d94b82deaf16e454ab2b0f9103f87eea8e13f424e59a09d9307e43227f6fcaa1989
|
data/README.md
ADDED
@@ -0,0 +1,339 @@
|
|
1
|
+
# motion-accessibility
|
2
|
+
|
3
|
+
# Making accessibility more accessible.
|
4
|
+
|
5
|
+
https://github.com/austinseraphin/motion-accessibility
|
6
|
+
|
7
|
+
Motion-Accessibility wraps the UIAccessibility protocols in nice
|
8
|
+
ruby. I hope that making them easier will encourage developers to use it
|
9
|
+
more and make their apps accessible.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'motion-accessibility'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install motion-accessibility
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
### UIAccessibility Informal Protocol
|
28
|
+
|
29
|
+
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.
|
30
|
+
|
31
|
+
#### Defining Attributes in a Custom Subclass
|
32
|
+
|
33
|
+
You can define these attributes in one of two ways. Firstly you can define a method in a subclass of UIView.
|
34
|
+
|
35
|
+
```
|
36
|
+
class CustomView < UIView
|
37
|
+
|
38
|
+
def accessibility_label
|
39
|
+
"Hello."
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
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.
|
46
|
+
|
47
|
+
#### Defining Attributes in the Instanciation Code
|
48
|
+
|
49
|
+
You can also set these attributes once you've defined a view.
|
50
|
+
|
51
|
+
```
|
52
|
+
view=UIView.alloc.init
|
53
|
+
view.accessibility_label="Hello."
|
54
|
+
```
|
55
|
+
|
56
|
+
#### `accessibility_label`
|
57
|
+
|
58
|
+
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.
|
59
|
+
|
60
|
+
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.
|
61
|
+
|
62
|
+
#### `accessibility_hint`
|
63
|
+
|
64
|
+
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.
|
65
|
+
|
66
|
+
#### `accessibility_traits`
|
67
|
+
|
68
|
+
Traits describe an element's state, behavior, or usage. They tell
|
69
|
+
VoiceOver how to respond to a view. To combine them, use the single vertical bar `|` binary or operator.
|
70
|
+
|
71
|
+
The `accessibility_attribute=` method accepts a symbol or array of symbols, and applies the accessibility_attribute method to them. For example, if a view displays an image that opens a link, you can do this.
|
72
|
+
|
73
|
+
```
|
74
|
+
class ImageLinkView < UIView
|
75
|
+
# ....
|
76
|
+
def accessibility_traits
|
77
|
+
:image.accessibility_trait|:link.accessibility_trait
|
78
|
+
end
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
Or, to set it in an instance of a view you can do this.
|
83
|
+
|
84
|
+
```
|
85
|
+
view=UIView.alloc.init
|
86
|
+
view.accessibility_traits=[:image, :link]
|
87
|
+
```
|
88
|
+
|
89
|
+
##### :none
|
90
|
+
The element does nothing.
|
91
|
+
##### :button
|
92
|
+
The view acts like a button.
|
93
|
+
##### :link
|
94
|
+
The view opens a link in Safari.
|
95
|
+
##### :search_field
|
96
|
+
The view acts like a search field.
|
97
|
+
##### :image
|
98
|
+
The view displays an image.
|
99
|
+
##### :selected
|
100
|
+
VoiceOver will report the element as selected. For example, a selected row in a table, or segment in a segmented control.
|
101
|
+
##### :keyboard_key
|
102
|
+
The view behaves like a keyboard key.
|
103
|
+
##### :header
|
104
|
+
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.
|
105
|
+
##### :static_text
|
106
|
+
The view displays static text.
|
107
|
+
##### :summary_element
|
108
|
+
The view provides summary information when the application starts.
|
109
|
+
##### :plays_sound
|
110
|
+
The view plays its own sound when activated.
|
111
|
+
#### :starts_media_session
|
112
|
+
Silences VoiceOver during a media session that should not be interrupted. For example, silence VoiceOver speech while the user is recording audio.
|
113
|
+
#### :updates_frequently
|
114
|
+
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.
|
115
|
+
#### :adjustable
|
116
|
+
The view has an adjustable value. Also see the `accessibility_increment` and `accessibility_decrement` methods.
|
117
|
+
#### :allows_direct_interaction
|
118
|
+
This tells VoiceOver to allow the user to interact directly with the view. For example, a piano keyboard.
|
119
|
+
#### :causes_page_turn
|
120
|
+
Causes an automatic page turn when VoiceOver finishes reading the text within it.
|
121
|
+
#### :not_enabled
|
122
|
+
Not enabled and does not respond to user interaction.
|
123
|
+
|
124
|
+
#### `accessibility_value`
|
125
|
+
|
126
|
+
The value reported in a slider, for example.
|
127
|
+
|
128
|
+
#### `accessibility_language`
|
129
|
+
|
130
|
+
The language used by VoiceOver to read the view.
|
131
|
+
|
132
|
+
#### `accessibility_frame`
|
133
|
+
|
134
|
+
The frame of the accessibility element. This defaults to the frame of the view. Remember to give it in screen coordinates, not the coordinates of the view.
|
135
|
+
|
136
|
+
#### `accessibility_activation_point`
|
137
|
+
|
138
|
+
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.
|
139
|
+
|
140
|
+
#### `accessibility_modal_view?` or `accessibility_view_is_modal`
|
141
|
+
|
142
|
+
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.
|
143
|
+
|
144
|
+
#### `group_accessibility_children?` or `should_group_accessibility_children`
|
145
|
+
|
146
|
+
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. Normally, VoiceOver reads 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.
|
147
|
+
|
148
|
+
#### `accessibility_elements_hidden?` or `accessibility_elements_hidden`
|
149
|
+
|
150
|
+
A boolean value which tells VoiceOver to hide the subviews of this view.
|
151
|
+
|
152
|
+
#### `accessibility_element?`, or `is_accessibility_element`
|
153
|
+
|
154
|
+
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.
|
155
|
+
|
156
|
+
#### `accessibility_identifier`
|
157
|
+
|
158
|
+
A unique identifier if you don't want to define the accessibility label.
|
159
|
+
|
160
|
+
### UIPickerView
|
161
|
+
|
162
|
+
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.
|
163
|
+
#### `accessibility_label_for_component`
|
164
|
+
Accepts an integer and returns the accessibility label for the component.
|
165
|
+
#### `accessibility_hint_for_component `
|
166
|
+
Accepts an integer and returns the accessibility hint for the component.
|
167
|
+
|
168
|
+
### UIAccessibility Actions
|
169
|
+
|
170
|
+
These methods trigger when the VoiceOver user performs specific actions. You can implement then in a UIView or an accessibility element.
|
171
|
+
|
172
|
+
#### `accessibility_perform_escape`
|
173
|
+
|
174
|
+
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.
|
175
|
+
|
176
|
+
#### `Accessibility_perform_magic_tap`
|
177
|
+
|
178
|
+
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.
|
179
|
+
|
180
|
+
#### `accessibility_scroll`
|
181
|
+
|
182
|
+
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.
|
183
|
+
|
184
|
+
#### Scroll Directions
|
185
|
+
|
186
|
+
`accessibility_scroll` takes one of the following scroll directions.
|
187
|
+
|
188
|
+
- :right
|
189
|
+
- :left
|
190
|
+
- :up
|
191
|
+
- :down
|
192
|
+
- :next
|
193
|
+
- :previous
|
194
|
+
|
195
|
+
#### `accessibility_increment`
|
196
|
+
|
197
|
+
Increments the value of the accessibility element. Make sure to have the :adjustable accessibility trait set for this to work.
|
198
|
+
|
199
|
+
#### `accessibility_decrement`
|
200
|
+
|
201
|
+
Decrements the value of the accessibility element. Make sure to have the :adjustable accessibility trait set for this to work.
|
202
|
+
|
203
|
+
### UIAccessibilityElement
|
204
|
+
|
205
|
+
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.new` with the container, usually self. Like a UIView, an accessibility element has attributes, and you get and set them in exactly the same way.
|
206
|
+
|
207
|
+
```
|
208
|
+
class CustomView < UIView
|
209
|
+
|
210
|
+
def initWithFrame(frame)
|
211
|
+
super
|
212
|
+
# …
|
213
|
+
accessibility=Accessibility::Element.new(self)
|
214
|
+
accessibility.label="Hello."
|
215
|
+
accessibility.frame=view.frame
|
216
|
+
accessibility.traits=:button
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
220
|
+
```
|
221
|
+
|
222
|
+
#### Container
|
223
|
+
|
224
|
+
The container of the accessibility element.
|
225
|
+
|
226
|
+
#### `label`
|
227
|
+
|
228
|
+
The accessibility label.
|
229
|
+
|
230
|
+
#### `hint`
|
231
|
+
|
232
|
+
The accessibility hint.
|
233
|
+
|
234
|
+
#### `frame`
|
235
|
+
|
236
|
+
The frame which VoiceOver should consider as the element. In a UIView this would default to the frame of the view.
|
237
|
+
|
238
|
+
#### `traits`
|
239
|
+
|
240
|
+
The accessibility traits. This works exactly like UIView.
|
241
|
+
|
242
|
+
#### `value`
|
243
|
+
|
244
|
+
The value of the element, if applicable.
|
245
|
+
|
246
|
+
#### `is_accessibility_element` or `accessibility_element?`
|
247
|
+
|
248
|
+
Returns true if VoiceOver should consider this an accessibility element. Note that you can only use `is_accessibility_element?=` as a setter.
|
249
|
+
|
250
|
+
### UIAccessibilityContainer Informal Protocol
|
251
|
+
|
252
|
+
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.
|
253
|
+
|
254
|
+
#### `accessibility_element_at_index`
|
255
|
+
Accepts an integer and returns the accessibility element. You can use the standard `Array#[]` method for this.
|
256
|
+
#### `accessibility_element_count`
|
257
|
+
Returns the number of accessible elements. You can use `Array#length` for this.
|
258
|
+
#### `index_of_accessibility_element`
|
259
|
+
Accepts an accessibility element and returns its index as an integer. You can use the `Array#index` method for this.
|
260
|
+
|
261
|
+
### UIAccessibilityFocus Informal Protocol
|
262
|
+
|
263
|
+
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.
|
264
|
+
#### `accessibility_element_did_become_focused`
|
265
|
+
Triggered when the accessibility element becomes focused by VoiceOver.
|
266
|
+
#### `accessibility_element_did_lose_focus`
|
267
|
+
Triggered when the accessibility element loses VoiceOver's focus.
|
268
|
+
#### `accessibility_element_focused?` or `accessibility_element_is_focused`
|
269
|
+
Returns true if the element currently has VoiceOver focus.
|
270
|
+
|
271
|
+
### UIAccessibilityReadingContent Informal Protocol
|
272
|
+
|
273
|
+
This protocol gives a seamless reading experience when dealing with
|
274
|
+
a UIView which contains long pieces of text, such as a book. -
|
275
|
+
#### `accessibility_content_for_line_number -`
|
276
|
+
Accepts an integer and returns the line of text to read.
|
277
|
+
#### `accessibility_frame_for_line_number -`
|
278
|
+
Accepts an integer and returns the frame which contains it.
|
279
|
+
#### `accessibility_line_number_for_point`
|
280
|
+
Accepts a CGPoint and returns the line number of the text to read.
|
281
|
+
|
282
|
+
### Notifications
|
283
|
+
|
284
|
+
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.
|
285
|
+
|
286
|
+
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
|
287
|
+
|
288
|
+
```
|
289
|
+
Accessibility.post_notification(:screen_changed)
|
290
|
+
```
|
291
|
+
|
292
|
+
Much easier, don't you think?
|
293
|
+
|
294
|
+
#### :layout_changed
|
295
|
+
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.
|
296
|
+
#### :screen_changed
|
297
|
+
Your application should post this notification when a major part of the screen changes. It has the same parameter as `:layout_changed`.
|
298
|
+
#### :page_scrolled
|
299
|
+
Post this notification after calling `Accessibility.scroll`. Include a string which describes the scrolling action, for example "Page 3 of 10".
|
300
|
+
#### :announcement
|
301
|
+
Post this notification to make VoiceOver output something. Just include the string.
|
302
|
+
#### :announcement_did_finish
|
303
|
+
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.
|
304
|
+
- :announcement_key_string_value
|
305
|
+
- :announcement_key_was_successful
|
306
|
+
#### :closed_captioning
|
307
|
+
UIKit posts this when the user toggles closed captioning.
|
308
|
+
#### :guided_access
|
309
|
+
UIKit posts this when the user toggles guided access.
|
310
|
+
#### :inverted_colors
|
311
|
+
UIKit posts this when the user toggles inverted colors.
|
312
|
+
#### :mono_audio
|
313
|
+
UIKit posts this when the user toggles mono audio.
|
314
|
+
#### :voiceover
|
315
|
+
UIKit posts this when the user toggles VoiceOver.
|
316
|
+
|
317
|
+
### Determining the Status of Accessibility Components
|
318
|
+
You can use these handy methods to determine the status of different accessibility components. They take no parameters and return true or false.
|
319
|
+
|
320
|
+
- `Accessibility.voiceover_running?`
|
321
|
+
- `Accessibility.closed_captioning_enabled?`
|
322
|
+
- `Accessibility.guided_access_enabled?`
|
323
|
+
- `Accessibility.invert_colors_enabled?`
|
324
|
+
- `Accessibility.mono_audio_enabled?`
|
325
|
+
|
326
|
+
Additionally, these two methods relate to the Zoom screen magnification software.
|
327
|
+
|
328
|
+
#### `Accessibility.zoom_focused_changed`
|
329
|
+
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.
|
330
|
+
#### `Accessibility.register_gesture_conflicts_with_zoom`
|
331
|
+
This issues a dialog to the user when a three-fingered gesture conflicts with Zoom. It lets them choose to disable Zoom or continue.
|
332
|
+
## contributing
|
333
|
+
|
334
|
+
|
335
|
+
1. Fork it
|
336
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
337
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
338
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
339
|
+
5. Create new Pull Request
|
@@ -0,0 +1,8 @@
|
|
1
|
+
unless defined?(Motion::Project::Config)
|
2
|
+
raise "This file must be required within a RubyMotion project Rakefile."
|
3
|
+
end
|
4
|
+
|
5
|
+
lib_dir_path = File.dirname(File.expand_path(__FILE__))
|
6
|
+
Motion::Project::App.setup do |app|
|
7
|
+
app.files.unshift(Dir.glob(File.join(lib_dir_path, "project/**/*.rb")))
|
8
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
class Accessibility
|
2
|
+
|
3
|
+
Attributes = {
|
4
|
+
:accessibility_identifier => :accessibilityIdentifier,
|
5
|
+
:accessibility_identifier= => :setAccessibilityIdentifier,
|
6
|
+
:accessibility_label => :accessibilityLabel,
|
7
|
+
:accessibility_label= => :setAccessibilityLabel,
|
8
|
+
:accessibility_hint => :accessibilityHint,
|
9
|
+
:accessibility_hint= => :setAccessibilityHint,
|
10
|
+
:accessibility_traits => :accessibilityTraits,
|
11
|
+
:accessibility_value => :accessibilityValue,
|
12
|
+
:accessibility_value= => :setAccessibilityValue,
|
13
|
+
:accessibility_language => :accessibilityLanguage,
|
14
|
+
:accessibility_language= => :setAccessibilityLanguage,
|
15
|
+
:accessibility_frame => :accessibilityFrame,
|
16
|
+
:accessibility_frame= => :setAccessibilityFrame,
|
17
|
+
:accessibility_activation_point => :accessibilityActivationPoint,
|
18
|
+
:accessibility_activation_point= => :setAccessibilityActivationPoint,
|
19
|
+
:accessibility_view_is_modal => :accessibilityViewIsModal,
|
20
|
+
:accessibility_view_is_modal= => :setAccessibilityViewIsModal,
|
21
|
+
:accessibility_modal_view? => :accessibilityViewIsModal,
|
22
|
+
:should_group_accessibility_children => :shouldGroupAccessibilityChildren,
|
23
|
+
:group_accessibility_children? => :shouldGroupAccessibilityChildren,
|
24
|
+
:should_group_accessibility_children= => :setShouldGroupAccessibilityChildren,
|
25
|
+
:accessibility_elements_hidden => :accessibilityElementsHidden,
|
26
|
+
:accessibility_elements_hidden? => :accessibilityElementsHidden,
|
27
|
+
:accessibility_elements_hidden= => :setAccessibilityElementsHidden,
|
28
|
+
:accessibility_element_did_become_focused => :accessibilityElementDidBecomeFocused,
|
29
|
+
:accessibility_element_did_lose_focus => :accessibilityElementDidLoseFocus,
|
30
|
+
:accessibility_element_is_focused => :accessibilityElementIsFocused,
|
31
|
+
:accessibility_element_focused? => :accessibilityElementIsFocused,
|
32
|
+
:accessibility_element? => :isAccessibilityElement,
|
33
|
+
:is_accessibility_element => :isAccessibilityElement,
|
34
|
+
:is_accessibility_element= => :isAccessibilityElement=
|
35
|
+
}
|
36
|
+
|
37
|
+
Element_Attributes = {
|
38
|
+
:container => :accessibilityContainer,
|
39
|
+
:container= => :setAccessibilityContainer,
|
40
|
+
:frame => :accessibilityFrame,
|
41
|
+
:frame= => :setAccessibilityFrame,
|
42
|
+
:hint => :accessibilityHint,
|
43
|
+
:hint= => :setAccessibilityHint,
|
44
|
+
:label => :accessibilityLabel,
|
45
|
+
:label= => :setAccessibilityLabel,
|
46
|
+
:traits => :accessibilityTraits,
|
47
|
+
:value => :accessibilityValue,
|
48
|
+
:value= => :setAccessibilityValue,
|
49
|
+
:did_become_focused => :accessibilityElementDidBecomeFocused,
|
50
|
+
:did_lose_focus => :accessibilityElementDidLoseFocus,
|
51
|
+
:is_focused => :accessibilityElementIsFocused,
|
52
|
+
:focused? => :accessibilityElementIsFocused,
|
53
|
+
:is_accessibility_element => :isAccessibilityElement,
|
54
|
+
:is_accessibility_element => :setIsAccessibilityElement,
|
55
|
+
:accessibility_element? => :isAccessibilityElement
|
56
|
+
}
|
57
|
+
|
58
|
+
Traits = {
|
59
|
+
none: UIAccessibilityTraitNone,
|
60
|
+
button: UIAccessibilityTraitButton,
|
61
|
+
link: UIAccessibilityTraitLink,
|
62
|
+
search_field: UIAccessibilityTraitSearchField,
|
63
|
+
image: UIAccessibilityTraitImage,
|
64
|
+
selected: UIAccessibilityTraitSelected,
|
65
|
+
keyboard_key: UIAccessibilityTraitKeyboardKey,
|
66
|
+
static_text: UIAccessibilityTraitStaticText,
|
67
|
+
header: UIAccessibilityTraitHeader,
|
68
|
+
summary_element: UIAccessibilityTraitSummaryElement,
|
69
|
+
plays_sound: UIAccessibilityTraitPlaysSound,
|
70
|
+
starts_media_session: UIAccessibilityTraitStartsMediaSession,
|
71
|
+
updates_frequently: UIAccessibilityTraitUpdatesFrequently,
|
72
|
+
adjustable: UIAccessibilityTraitAdjustable,
|
73
|
+
allows_direct_interaction: UIAccessibilityTraitAllowsDirectInteraction,
|
74
|
+
causes_page_turn: UIAccessibilityTraitCausesPageTurn,
|
75
|
+
not_enabled: UIAccessibilityTraitNotEnabled
|
76
|
+
}
|
77
|
+
|
78
|
+
PickerView_Attributes = {
|
79
|
+
:accessibility_label_for_component => :accessibilityLabelForComponent,
|
80
|
+
:accessibility_abel_for_component= => :setAccessibilityLabelForComponent,
|
81
|
+
:accessibility_hint_for_component => :accessibilityHintForComponent,
|
82
|
+
:accessibility_hint_for_component= => :setAccessibilityHintForComponent
|
83
|
+
}
|
84
|
+
|
85
|
+
Container_Attributes = {
|
86
|
+
:accessibility_element_at_index => :accessibilityElementAtIndex,
|
87
|
+
:accessibility_element_count => :accessibilityElementCount,
|
88
|
+
:index_of_accessibility_element => :indexOfAccessibilityElement
|
89
|
+
}
|
90
|
+
|
91
|
+
Reading_Content = {
|
92
|
+
accessibility_content_for_line_number: :accessibbilityContentForLineNumber,
|
93
|
+
accessibility_frame_for_line_number: :accessibilityFrameForLineNumber,
|
94
|
+
accessibility_line_number_for_point: :accessibilityLineNumberForPoint,
|
95
|
+
accessibility_page_content: :accessibilityPageContent
|
96
|
+
}
|
97
|
+
|
98
|
+
Actions = {
|
99
|
+
:accessibility_decrement => :accessibilityDecrement,
|
100
|
+
:accessibility_increment => :accessibilityIncrement,
|
101
|
+
:accessibility_perform_escape => :accessibilityPerformEscape,
|
102
|
+
:accessibility_perform_magic_tap => :accessibilityPerformMagicTap,
|
103
|
+
:accessibility_scroll => :accessibilityScroll
|
104
|
+
}
|
105
|
+
|
106
|
+
All_Attributes=Attributes.merge(Container_Attributes).merge(Reading_Content).merge(Actions)
|
107
|
+
|
108
|
+
Notifications = {
|
109
|
+
:layout_changed => UIAccessibilityLayoutChangedNotification,
|
110
|
+
:screen_changed => UIAccessibilityScreenChangedNotification,
|
111
|
+
:page_scrolled => UIAccessibilityPageScrolledNotification,
|
112
|
+
:announcement => UIAccessibilityAnnouncementNotification,
|
113
|
+
:announcement_did_finish => UIAccessibilityAnnouncementDidFinishNotification,
|
114
|
+
:closed_captioning => UIAccessibilityClosedCaptioningStatusDidChangeNotification,
|
115
|
+
:guided_access => UIAccessibilityGuidedAccessStatusDidChangeNotification,
|
116
|
+
:invert_colors => UIAccessibilityInvertColorsStatusDidChangeNotification,
|
117
|
+
:mono_audio => UIAccessibilityMonoAudioStatusDidChangeNotification,
|
118
|
+
:voiceover => UIAccessibilityVoiceOverStatusChanged
|
119
|
+
}
|
120
|
+
|
121
|
+
def Accessibility.post_notification(notification, *args)
|
122
|
+
if(notification.kind_of?(Fixnum))
|
123
|
+
UIAccessibilityPostNotification(notification, *args)
|
124
|
+
elsif(notification.kind_of?(Symbol))
|
125
|
+
raise "You cannot post #{notification} as an accessibility notification" unless Notifications[notification].kind_of?(Fixnum)
|
126
|
+
UIAccessibilityPostNotification(Notifications[notification], *args)
|
127
|
+
else
|
128
|
+
raise "Unknown accessibility notification #{notification}"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
Scroll_Directions = {
|
133
|
+
:right => UIAccessibilityScrollDirectionRight,
|
134
|
+
:left => UIAccessibilityScrollDirectionLeft,
|
135
|
+
:up => UIAccessibilityScrollDirectionUp,
|
136
|
+
:down => UIAccessibilityScrollDirectionDown,
|
137
|
+
:next => UIAccessibilityScrollDirectionNext,
|
138
|
+
:previous => UIAccessibilityScrollDirectionPrevious
|
139
|
+
}
|
140
|
+
|
141
|
+
Zoom = {
|
142
|
+
:announcement_key_string_value => UIAccessibilityAnnouncementKeyStringValue,
|
143
|
+
:announcement_key_was_successful => UIAccessibilityAnnouncementKeyWasSuccessful
|
144
|
+
}
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
class Symbol
|
149
|
+
|
150
|
+
def accessibility_trait
|
151
|
+
Accessibility::Traits[self]||(raise("Unknown accessibility trait #{trait}"))
|
152
|
+
end
|
153
|
+
|
154
|
+
def accessibility_notification
|
155
|
+
Accessibility::Notifications[self]||(raise "Unknown accessibility notification #{self}")
|
156
|
+
end
|
157
|
+
|
158
|
+
def accessibility_scroll_direction
|
159
|
+
Accessibility::Scroll_Directions[self]||(raise "Unknown accessibility scroll direction #{self}")
|
160
|
+
end
|
161
|
+
|
162
|
+
def accessibility_zoom_type
|
163
|
+
Accessibility::Zoom[self]||(raise("Unknown zoom type #{self}"))
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class UIAccessibilityElement
|
2
|
+
|
3
|
+
def initialize(container)
|
4
|
+
raise "Please initialize with a container, usually self." unless container
|
5
|
+
UIAccessibilityElement.alloc.initWithAccessibilityContainer(self)
|
6
|
+
end
|
7
|
+
|
8
|
+
alias :init_with_accessibility_container :initialize
|
9
|
+
|
10
|
+
Accessibility::Element_Attributes.each do |ruby,ios|
|
11
|
+
if ruby=~/=$/
|
12
|
+
define_method(ruby) {|value| self.send(ios,value)}
|
13
|
+
else
|
14
|
+
define_method(ruby) {self.send(ios)}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def accessibility_traits=(traits)
|
19
|
+
bits=0
|
20
|
+
if traits.kind_of?(Fixnum)
|
21
|
+
bits=traits
|
22
|
+
elsif traits.kind_of?(Symbol)
|
23
|
+
bits=traits.accessibility_trait
|
24
|
+
elsif traits.kind_of?(Array)
|
25
|
+
traits.each {|trait| bits|=trait.accessibility_trait}
|
26
|
+
else
|
27
|
+
raise "Pass a bitmask, a symbol, or an array to accessibility_traits="
|
28
|
+
end
|
29
|
+
OAself.accessibilityTraits=bits
|
30
|
+
end
|
31
|
+
|
32
|
+
if self.respond_to?(:method_added)
|
33
|
+
alias :method_added_accessibility :method_added
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.method_added(name)
|
37
|
+
if self.respond_to?(:method_added_accessibility)
|
38
|
+
method_added_accessibility(name)
|
39
|
+
end
|
40
|
+
return if name=~/=$/
|
41
|
+
attributes=Accessibility::Element_Attributes
|
42
|
+
return unless attributes.flatten.grep(%r{name.to_sym})
|
43
|
+
if attributes.has_key?(name)
|
44
|
+
ruby=name
|
45
|
+
ios=attributes[name]
|
46
|
+
if ios==:accessibilityElementIsFocused
|
47
|
+
raise "You cannot define #{ruby}"
|
48
|
+
end
|
49
|
+
define_method(ios) {self.send(ruby)}
|
50
|
+
else
|
51
|
+
ios=name
|
52
|
+
ruby=attributes.rassoc(name).first
|
53
|
+
define_method(ruby) { self.send(ios)}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
Accessibility::Element=UIAccessibilityElement
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class NSObject
|
2
|
+
|
3
|
+
Accessibility::Attributes.each do |ruby, ios|
|
4
|
+
next if ruby==:accessibility_traits=
|
5
|
+
if ruby=~/=$/
|
6
|
+
define_method(ruby) {|value| self.send(ios,value)}
|
7
|
+
else
|
8
|
+
define_method(ruby) {self.send(ios)}
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
Accessibility::Container_Attributes.each do |ruby, ios|
|
13
|
+
if ruby=="accessibility_element_count"
|
14
|
+
define_method(ruby) {self.send(ios)}
|
15
|
+
else
|
16
|
+
define_method(ruby) {|n| self.send(ios,n)}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Accessibility::Actions.each {|ruby,ios| define_method(ruby) {ios}}
|
21
|
+
|
22
|
+
def accessibility_traits=(traits)
|
23
|
+
bits=0
|
24
|
+
if traits.kind_of?(Fixnum)
|
25
|
+
bits=traits
|
26
|
+
elsif traits.kind_of?(Symbol)
|
27
|
+
bits=traits.accessibility_trait
|
28
|
+
elsif traits.kind_of?(Array)
|
29
|
+
traits.each {|trait| bits|=trait.accessibility_trait}
|
30
|
+
else
|
31
|
+
raise "Pass a bitmask, a symbol, or an array to accessibility_traits="
|
32
|
+
end
|
33
|
+
self.accessibilityTraits=bits
|
34
|
+
end
|
35
|
+
|
36
|
+
if self.respond_to?(:method_added)
|
37
|
+
class << self
|
38
|
+
alias :method_added_accessibility :method_added
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.method_added(name)
|
43
|
+
if self.respond_to?(:method_added_accessibility)
|
44
|
+
method_added_accessibility(name)
|
45
|
+
end
|
46
|
+
return if name=~/=$/
|
47
|
+
attributes=Accessibility::All_Attributes
|
48
|
+
return unless attributes.flatten.include?(name.to_sym)
|
49
|
+
if attributes.has_key?(name)
|
50
|
+
ruby=name
|
51
|
+
ios=attributes[name]
|
52
|
+
define_method(ios) {self.send(ruby)}
|
53
|
+
else
|
54
|
+
ios=name
|
55
|
+
ruby=attributes.rassoc(name).first
|
56
|
+
define_method(ruby) { self.send(ios)}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class UIPickerView
|
2
|
+
|
3
|
+
Accessibility::PickerView_Attributes.each {|ruby,ios| define_method(ruby) {|component| self.send(ios, component)}}
|
4
|
+
|
5
|
+
if self.respond_to?(:method_added)
|
6
|
+
class << self
|
7
|
+
alias :method_added_accessibility :method_added
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.method_added(name)
|
12
|
+
if self.respond_to?(:method_added_accessibility)
|
13
|
+
method_added_accessibility(name)
|
14
|
+
end
|
15
|
+
return unless Accessibility::PickerView_Attributes.flatten.grep(%r{name.to_sym})
|
16
|
+
if Accessibility::PickerView_Attributes.has_key?(name)
|
17
|
+
ruby=name
|
18
|
+
ios=Accessibility::PickerView_Attributes[name]
|
19
|
+
define_method(ios) {|component| self.send(ruby, component)}
|
20
|
+
else
|
21
|
+
ios=name
|
22
|
+
ruby=Accessibility::PickerView_Attributes.rassoc(name).first
|
23
|
+
define_method(ruby) {|component| self.send(ios, component)}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Miscellaneous aliases to determine the status of accessibility components
|
2
|
+
|
3
|
+
class Accessibility
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def voiceover_running?
|
7
|
+
UIAccessibilityIsVoiceOverRunning()
|
8
|
+
end
|
9
|
+
def closed_captioning_enabled?
|
10
|
+
UIAccessibilityIsClosedCaptioningEnabled()
|
11
|
+
end
|
12
|
+
def guided_access_enabled?
|
13
|
+
UIAccessibilityIsGuidedAccessEnabled()
|
14
|
+
end
|
15
|
+
def invert_colors_enabled?
|
16
|
+
UIAccessibilityIsInvertColorsEnabled()
|
17
|
+
end
|
18
|
+
def mono_audio_enabled?
|
19
|
+
UIAccessibilityIsMonoAudioEnabled()
|
20
|
+
end
|
21
|
+
def zoom_focused_changed(zoom, frame, view)
|
22
|
+
zoom=zoom.accessibility_zoom_type if zoom.kind_of?(Symbol)
|
23
|
+
UIAccessibilityZoomFocusChanged(zoom,frame,view)
|
24
|
+
end
|
25
|
+
def registered_gesture_conflict_with_zoom
|
26
|
+
UIAccessibilityRegisterGestureConflictWithZoom()
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: motion-accessibility
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '1.0'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Austin Seraphin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: AA RubyMotion wrapper around the UIAccessibility procotols
|
28
|
+
email:
|
29
|
+
- austin@austinseraphin.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- README.md
|
35
|
+
- lib/motion-accessibility.rb
|
36
|
+
- lib/project/constants.rb
|
37
|
+
- lib/project/element.rb
|
38
|
+
- lib/project/motion-accessibility.rb
|
39
|
+
- lib/project/object.rb
|
40
|
+
- lib/project/picker.rb
|
41
|
+
- lib/project/status.rb
|
42
|
+
homepage: https://github.com/austinseraphin/motion-accessibility
|
43
|
+
licenses:
|
44
|
+
- GPL
|
45
|
+
metadata: {}
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 2.0.3
|
63
|
+
signing_key:
|
64
|
+
specification_version: 4
|
65
|
+
summary: This gem provides easy ruby-like wrappers around the protocols which interact
|
66
|
+
with VoiceOver and other assistive technologies. Making accessibility accessible!
|
67
|
+
test_files: []
|