VoiceOver: force an accessibility element to be selected after a screen transition - objective-c

I'm in the process of making my iOS app accessible and I'm nearly finished. My app contains several custom screen transitions, and when VoiceOver is on it seems to pick either the top-leftmost element to describe after the transition or, occasionally, a random element. UIAccessibilityTraitSummaryElement looked promising but as I understand it only works when the app is started, not after arbitrary transitions.
There doesn't seem to be an accessibility trait or property to specify the preferred order that elements are given VoiceOver focus. Is there any way to force VoiceOver focus?

EDIT: iOS 6 is now available, and as mentioned by kevboh, you can now pass an argument when posting a UIAccessibilityLayoutChangedNotification or UIAccessibilityScreenChangedNotification:
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, myAccessibilityElement);
myAccessibilityElement will in most cases be a UIView with isAccessibilityElement set to YES (the default for many views).
Alternatively, you could add the new trait added in iOS6 UIAccessibilityTraitHeader to your accessibility elements' accessibilityTraits, which should have the same result (although I didn't test this yet).
ORIGINAL: There's new API in iOS 6 that can't be discussed here because it is still under NDA, but can be found in the "Accessibility for iOS" video of WWDC 2012 (Session 210).
Failing that though, a workaround could be to manually trigger a announcement to override the default focused accessibility label announcement:
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, #"Your text");

Interesting explanations to force the VoiceOver focus and reorder the elements as wished are provided thanks to this accessibility recommendations site.
NOTIFY A CONTENT CHANGE
When there is a content change in the current page, it is possible to notify the accessibility API using several types of notifications. To do that, we must send the change notification to the accessibility API using the method UIAccessibilityPostNotification.
There are several types of change notifications but the two most commonly used are:
UIAccessibilityLayoutChangedNotification : notifies that a part of the page has changed with 2 possible incoming parameters (a NSString or a UIObject).
With a NSString, the notification behaves like a UIAccessibilityAnnouncementNotification with a VoiceOver vocalization.
With a UIObject, focus is shifted to the user interface element.
This notification is very similar to the UIAccessibilityAnnouncementNotification but should come as a result of dynamic content being deleted or added to the current view.
UIAccessibilityScreenChangedNotification : notifies that the whole page has changed including nil or a UIObject as incoming parameters.
With nil, the first accessible element in the page is focused.
With a UIObject, focus is shifted to the specified element with a VoiceOver.
This notification comes along with a vocalization including a sound like announcing a new page.
READING ORDER
Redefining the VoiceOver reading order is done using the UIAccessibilityContainer protocol. The idea is to have a table of elements that defines the reading order of the elements. It is often very useful to use the shouldGroupAccessibilityElement attribute so we have a precise order but for a part of the view only (the rest of the view will be read using the native order provided by VoiceOver).
The best way to illustrate this feature is the keyboard whose keys order isn't necessary the appropriate one.
Here's the desired order : 1, 2, 3, 4, 7, 6, 8, 9, 5.
Two views are created (blue and grey) and we graphically put the numbers in them as defined hereunder :
Illustrations and code snippets (Swift & ObjC) are also available to defining these 2 explanations.

Related

How do I notify users of new content available in tvOS apps from the home screen?

Push notifications have been left out of tvOS (understandably so) but the docs seem to contradict themselves in alerting users to the fact that there is something new available in your tvOS app.
Here it seems to say that you can add an app badge: https://developer.apple.com/library/prerelease/tvos/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/WhatAreRemoteNotif.html
Here it says they've been removed from UIKit: https://developer.apple.com/library/prerelease/tvos/releasenotes/General/tvOS90APIDiffs/Objective-C/UIKit.html
Removed UIApplication.applicationIconBadgeNumber
Assuming the badge approach is not supported in this release, does anyone know the best practice for alerting a user that there is new content in your app without the user taking an explicit action? ie focusing on the app and showing them something in TopShelf?
I encountered the same problem and dived into this. Probably your best way is to update the topshelf with latest items, which is my way to solve this for now. You can use network calls to update the topshelf with content from your backend.
This depends on the type of application. E.g. showing the latest top movies for a movies app.
You can trigger an update of the topshelf after your network call completed using the following code:
NSNotificationCenter.defaultCenter().postNotificationName(TVTopShelfItemsDidChangeNotification, object: nil)
Make sure to implement the TVTopShelfProvider which should be clear using the following documentation:
This protocol is adopted by the principal class of an app’s TV Services extension. Apps that implement this extension can provide dynamic content to the Top Shelf element rather than having the system use the static image submitted with the app. The topShelfStyle property specifies the interface style you want, and the topShelfItems property specifies the content items to display. Whenever you change the content provided by the extension, post a TVTopShelfItemsDidChangeNotification notification to prompt the system to reload your content.
Icon badges are removed for app icons, push notifications as well (except for silent push notifications).

Identify the monitor with the browser window in FireBreath

I am using FireBreath to create a cross browser plugin which makes use of some native libraries for the respective platform (some .NET based DLLs for Windows and Objective-C based dylibs/frameworks for Mac). Native libraries display UI screens. In order to improve usability, if the user has a multi/extended monitor setup, i would like the native UIs to appear on the same screen as the browser window is currently on.
If an identifier to the monitor with the browser window can be retrieved, that can be passed down to the native components which can be configured to display their UIs on that monitor. I have used FireBreath's getWindowPosition() method to get the rect coordinates of the plugin and used that info to identify the correct monitor in the Windows platform.
However, the coordinates returned in Mac seems to be always 0 (or 1) irrespective of monitor on which the browser window currently resides. I understand that we have to configure an event model and a drawing model in order for this to work in Mac. I have tried following event/drawing model combinations without much success.
1) Cocoa/CoreGraphics
2) Carbon/CoreGraphics
Any help in this regard is much appreciated. Also please do share if there are other approaches to achieve the same. What i want to achieve is to identify the monitor on which the current active browser window resides in Mac. I am unsure at this point, but it maybe possible to achieve this at Objective-C level (without any changes at FireBreath level). Also please note that i want to support Safari, Firefox and Chrome browsers.
You won't like this answer, but simply put you can't do that on Mac. The problem is that with CoreGraphics you are only given a CGContextRef to work with, and it doesn't know where it will be drawn. It was technically possible in older browsers to get an NSWindow by exploiting some internal implementation details, but many browsers that's no longer possible and it was never supported.
Other drawing models are the same; CoreAnimation you have a CALayer but it doesn't know which screen or monitor it is drawn to. I personally think it's a bit annoying as well, but I do not know of any way to find out which monitor your plugin is rendered to, particularly since most of them actually copy the buffer to something else and render in a different process.
I did manage to come up with a workaround and i am just replying here for the completeness of the thread. As #taxilian explained, it is not possible to retrieve plugin coordinates using the window reference. As an alternative approach, Javascript 'Window' object has 2 properties called 'screenX' and 'screenY' that return X and Y coordinates of the browser window relative to the screen. If the user has an extended monitor setup, these are the absolute coordinates with respect to the full extended screen. We can use these values to determine the monitor with the browser window (if the X coordinate is outside the bounds of the primary monitor's width, then the browser should essentially be on the extended monitor). We can retrieve DOM properties from Firebreath as explained in the following link:
http://www.firebreath.org/display/documentation/Invoking+methods+on+the+DOM

Make input in program input value at website

I want a function in my JavaFX 2.0 program that takes user input and forwards it to a websites textfield, and then get the value the website returns. The website would be a site to check if the warranty for a spesific program is valid.
All the user would need to input is reg. ID and maybe program brand.
I'm just looking for ideas on how to do this, links or even code would be superb. I suspect it won't require that much code, but hey.. i've been surprised before!
Thanks! :)
A possible implementation algorithm:
Load the warranty check page in the WebView.
Monitor the webEngine.documentProperty to check for when the load has finished.
When the load has finished, use webEngine.executeScript to set the text field to the
required value and submit the form.
EITHER
a. monitor the webEngine.documentProperty some more, and, when the document has loaded, inspect the document (using either JavaScript or Java) to see if the warranty is valid.
OR
b. change the resultant warranty display page to call back into Java and notify your app of the warranty status.
Some background info
If you have control over the website page contents, then your implementation may turn out easier. But I think you should still be able to get the result you want without modifying the website.
There were some additions to the recent JavaFX 2.1 release to facilitate callbacks from Javascript to Java. The webview documentation you want to read is the sections "Processing JavaScript Commands" using the webEngine.executeScript method and "Making Upcalls from JavaScript to JavaFX" using JSObject.setMember.
You might want to also take a look at a Sample DatePicker for JavaFX using jQuery UI example I wrote. It demonstrates various methods for loading html into a WebView, invoking functions on the WebView from Java and getting the results of user interactions with the WebView back into Java. Not exactly what you are looking for, but perhaps the ideas in it may help.
Another option you have is just to:
Accept the registration id in a JavaFX control.
Create a java.net.URL and post to the webserver from your java app directly without using a WebView.
Parse the response from the webserver to extract out whether the warranty is valid.
This is the approach I might take for such a task - eliminating the use of WebView completely.

Getting the screen position of a non-view based NSStatusItem

My application makes use of an NSStatusItem. I need to grab the screen coordinates for the status item, but since I have no need for the functionality offered by setting a custom view for the item I am using a standard icon-based one instead.
Is there a way to get the status item's position without having to resort to setting a custom view to it?
Unless you find a better way, you could use some undocumented API: - (id)_window of NSStatusItem probably returns the window enclosing the item itself. Maybe you can get some interesting information out of that?
Beware: Some fundamentalists might actually try to break your neck for using undocumented API. Just make sure you check regularly if this portion of your code works with newer OS versions (either by hand or using some unit tests).

Quicklook embedded preview

From the docs for quicklook:
"The consumer portion of Quick Look
has three components: a document
reader (consisting of a custom view
and panel), display bundles for that
reader, and an SPI to enable
communication with the client. Each of
these components has a specific role
to play in support of the consumer:
Document reader—Quick Look implements
a view (NSView) and panel (NSPanel)
customized for displaying document
previews. Along with the preview
content, the view might include (at
the client’s option) controls for
manipulating the preview, such as
page-forward, page-backward, start
playing, rewind, and text-search. A
client application can embed this view
in its user interface if it chooses.
The Quick Look panel contains a Quick
Look view and various controls that
let the user take some action with the
preview, such making the preview image
full-screen or starting a slideshow."
I have been poring through all the docs and examples for quicklook and I don't see either:
A definition of any sort of "Document reader" component or way to access it.
Any sort of SPI as such that would show how to consumer quicklook
Any direct access to the NSView used by quicklook to display previews.
All I want to to do as the docs say: embed quicklook's view in my own hierarchy rather than in the Panel. The panel of course has abundant documentation. Has anyone successfully used Quicklook in this manner before?
The class you are looking for is QLPreviewView, part of Quartz.framework. It's a public class (introduced in Lion, I believe). Unfortunately, the docs team apparently hasn't yet released its documentation, which is probably why you couldn't find it. The official docs are now available.
The short, short version is that you create it the way you would any other view, and set its previewItem to an id <QLPreviewItem> that you supply. The <QLPreviewItem> protocol is documented. E.g.
QLPreviewView *pv = [[QLPreviewView alloc] initWithFrame:frame
style:QLPreviewViewStyleNormal];
[pv setPreviewItem:item];
[myView addSubview:pv];
[pv release];
That's the basic concept, YMMV.
Its operation is thoroughly covered in the 2011 WWDC session "System-wide Previews on Mac OS X and iOS" (or something to that effect). You should be able to get the video if you are a paid member of either the Mac OS X or iOS developer programs.