motion-accessibility 1.0

Sign up to get free protection for your applications and to get access to all the features.
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,6 @@
1
+ class Motion
2
+ class Accessibility
3
+
4
+ end
5
+ end
6
+
@@ -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: []