[ Music ]
Hi. I'm Conor Hughes from the iOS Accessibility team and I'm here to talk about making your drags and drops in iOS accessible.
Let's get started.
Let's briefly go over what we're going to cover.
We'll start with a very brief refresher of the basics of Drag and Drop.
Then, we'll go into come concepts behind the Accessibility Drag and Drop API.
And then, we'll go into some examples, first, exposing an ancestor's drag from an accessibility element, and then exposing multiple drops from an Accessibility element.
To recap Drag and Drop at a high level, Drag and Drop is a technology introduced with iOS 11 and provides powerful ways for someone using your application to transfer data both within the application and between applications.
Drag and Drop introduced the concept of interactions, which are hosted by views in your application.
To start a drag from a view, you add a UIDrag interaction object to it.
To accept a drop, you add a UIDrop interaction.
If you're not familiar with these classes you should watch the Introducing Drag and Drop session from WWDC2017 for more information, and then come back to this video.
Now, let's start to talk about accessibility.
Of course, you want to expose the power of your Drag and Drop interactions to people using your app through an assistive technology like Voiceover.
There are a few accessibility problems the accessibility Drag and Drop API's were designed to solve.
First, your accessibility element might not host interactions directly.
For instance, your accessibility element might be a view whose subviews host interactions.
Or your element might descend from a view that hosts interactions that are logically associated with it.
The solution is that the Accessibility Drag and Drop API's allow you to specify logical drags and drops to the system in a way that makes them usable with assistive technologies.
Let's get into those API's now.
The UIAccessibilityDragging informal protocol defines two properties that you use to express drags and drops to Accessibility.
It deals with the concept of Drag Sources and Drop Points.
Drag Sources describe where to start drags that are associated with an element and Drop Points describe places associated with an element where items can be dropped.
To use these properties, you can assign to them or override the getter to provide data on demand.
These drags and drops are exposed to users of assistive technologies in much the same way as Accessibility custom actions are.
So, that's the API, there.
Often, drags and drops are exposed automatically to Accessibility by the system.
And if they're found automatically they're assigned a default name but note that only interactions in an element subtree are automatically exposed.
The UIAccessibilityDragging protocol allows you to expose exactly the interactions that make sense, wherever they may actually live in your View hierarchy.
Allows you to specify a great name for each one.
So, you should really consider implementing it to provide the best experience for someone using your application through an assistive technology.
Now, let's look at an example of how you can expose drags with the UIAccessibilityDragging informal protocol.
Let's say we're building a bar graph and we've chosen to draw the bars by configuring CALayer objects.
And we're going to try and enable dragging of the bars themselves, to drag the bar data.
So, here is an example of how that might look.
And again, each of these bars is going to be a CALayer object.
How would we go about implementing drag for this?
It might look something like this.
Note that because layers aren't views they can't host interactions.
So, the bar graph itself has the interaction installed.
And in this itemsForBeginning session callback, depending on the bar that is hit tested, we return different data in the drag item.
Note that even though I only have one drag interaction I am using it to support multiple logical drags.
This is a totally supported approach and it is an example of how powerful, in general, the base Drag and Drop API's are.
Now, how do you make this accessible?
A good approach to making a graph like this accessible is to expose each bar as an Accessibility element, which I've done here.
Note that what I'm doing here is providing data about the logical structure of my app's content to the Accessibility Runtime.
That enables assistive technologies to expose the content in a different way.
We'll need to do the same thing to make the drags accessible, and to do so we'll need to learn some more specifics about the UIAccessibilityDragging informal protocol.
First, let's learn about the class UIAccessibility LocationDescriptor.
This class is data that describes where an interaction is by specifying a point in a view with a particular name.
So, for an example in our bar graph, a location descriptor for dragging that bar there, might look like this.
Its name might be Drag Bar Data.
The view would be the bar graph view itself.
And the point would be a point that's located within the bar.
So, what do we do with UIAccessibility LocationDescriptor options?
Well, we assign them to the two properties mentioned earlier.
The two properties in the protocol are accessibilityDrag SourceDescriptors and accessibilityDrop PointDescriptors.
DragSourceDescriptors is used to expose drag sources that are logically associated with an element and DropPointDescriptors exposes places to drop that are logically associated with this element.
These are the properties you use to describe to Accessibility what can be dragged from and dropped into a given element.
One important point to be aware of is that the descriptors must reference the View that actually has the interaction.
So, for instance, you shouldn't reference a point in your window that happens to be within the View that hosts the interaction.
You should specify that view itself.
So, pulling it together; to expose a single drag from some element doesn't take that much code, at all.
You make a Descriptor that specifies that drag by specifying a point in the View that hosts the interaction and giving it a name.
And then, you set the accessibilityDrag SourceDescriptors property element to an array that includes that descriptor.
Let's go back to our bar graph code that set the Accessibility elements of the graph view.
What do we need to do to expose dragging each element?
We compute a point within the bar represented by that element in the View's coordinate space, make an appropriate descriptor with that point in that View.
And set the accessibilityDrag SourceDescriptors property of the element.
And that's it.
Now, let's look at a slightly different example.
Let's try to expose multiple drops from a single element.
This might be useful for a situation like a contact card, where the card is small enough that we're going to expose it as one element to Accessibility.
But there are multiple wells into which we can drop content into the card.
So, for instance, it might have a portrait and a space for you to drop arbitrary attachments for that contact.
Now, that we know how to use the UIAccessibilityDragging informal protocol, exposing these is straightforward.
We can override the accessibilityDrop PointDescriptors getter of the View, compute the midpoints of the two wells, and then return two location descriptors that name each drop point.
So, in summary, because you want everyone to be able to use all the cool features you build into your app, you want to make sure that the drags and drops associated with Accessibility elements in your app are exposed to assistive technologies.
To do so, use the accessibilityDrag SourceDescriptors property to specify what drag should be exposed, and the accessibilityDrop PointDescriptors property to specify what drop should be exposed.
Finally, these properties are just arrays of UIAccessibility LocationDescriptor objects, which describe to Accessibility where these drags and drops are in your application and how to activate them.
For more information, you can check out this video online.
And thanks for watching.