iOS 11 introduced drag and drop, a feature that allows users to easily move or copy data within or between apps. With drag and drop, users can:
- Select items to drag
- Add extra items to a drag after it has started
- Transfer data asynchronously between applications
On iPads, drag and drop works within or between applications. On iPhones, drag and drop is restricted to a single app.
Drag and Drop Sample App
This post describes how the drag and drop APIs are used in a single-screen iPhone app that has users sort even and odd numbers:
To follow along, download the code for the EvenOddNumberDrag app.
Enable User Interaction
Three elements of the app’s user interface (found in Main.storyboard) are relevant to dragging and dropping:
NumberLabel
displays the number which is to be dragged.EvenNumbersLabel
is the label on which even numbers should be dropped.OddNumbersLabel
is the label on which odd numbers should be dropped.
Since users will be interacting with these labels, each must have its UserInteractionEnabled
property set to true
. This is done in ViewController.cs:
protected void SetupDragAndDrop()
{
NumberLabel.UserInteractionEnabled = true;
EvenNumbersLabel.UserInteractionEnabled = true;
OddNumbersLabel.UserInteractionEnabled = true;
// …
}
Enable Dragging
A basic drag interaction requires only a few pieces:
- A
UIDragInteraction
object that is attached to the view that will be draggable and explicitly enabled:protected void SetupDragAndDrop() { // … var numberDragInteraction = new UIDragInteraction(this); NumberLabel.AddInteraction(numberDragInteraction); // On iPad, this defaults to true. On iPhone, this defaults to // false. Since this app should work on the iPhone, enable the // drag interaction. numberDragInteraction.Enabled = true; // … }
- An
IUIDragInteractionDelegate
that acts as the delegate for the drag interaction object. In this sample,ViewController
itself is theIUIDragInteractionDelegate
. Only one of the delegate methods needs to be implemented:public UIDragItem[] GetItemsForBeginningSession(UIDragInteraction interaction, IUIDragSession session) { bool isEven = Convert.ToInt16(NumberLabel.Text) % 2 == 0; var provider = new NSItemProvider(new NSString(NumberLabel.Text)); var item = new UIDragItem(provider) { LocalObject = new NSNumber(isEven) }; return new UIDragItem[] { item } ; }
This method returns an array of
UIDragItem
objects, each representing a piece of data to be included in the drag and drop operation. Each drag item contains anNSItemProvider
that holds a representation of the data to be transferred.In this case, the
NSItemProvider
is given anNSString
, which implements theINSItemProviderWriting
interface, one of the data representations supported byNSItemProvider
.The
UIDragItem
has aLocalObject
property that is accessible only within the application that initiated the drag. Since this example focuses on a single app, for convenienceGetItemsForBeginningSession
sets theLocalObject
to aNSNumber
. This represents whether or not the dragged number is even.
Enable Dropping
To enable a drop interaction, you will need:
- A
UIDropInteraction
object for each view on which items can be dropped:protected void SetupDragAndDrop() { // … evenDropInteraction = new UIDropInteraction(this); EvenNumbersLabel.AddInteraction(evenDropInteraction); oddDropInteraction = new UIDropInteraction(this); OddNumbersLabel.AddInteraction(oddDropInteraction); }
- An
IUIDropInteractionDelegate
object. In this sample,ViewController
serves as the drop delegate. - An implementation of the
SessionDidUpdate
method from theIUIDropInteractionDelegate
interface extension methods:[Export("dropInteraction:sessionDidUpdate:")] public UIDropProposal SessionDidUpdate(UIDropInteraction interaction, IUIDropSession session) { UIDropProposal proposal; var isEven = (session.Items[0].LocalObject as NSNumber).BoolValue; if (interaction == oddDropInteraction && !isEven) { proposal = new UIDropProposal(UIDropOperation.Copy); } else if (interaction == evenDropInteraction && isEven) { proposal = new UIDropProposal(UIDropOperation.Copy); } else { proposal = new UIDropProposal(UIDropOperation.Forbidden); } return proposal; }
This method is called any time there’s a change that will potentially affect the outcome of the drop; for example, when the drop location changes in the target view because the user has moved the item being dragged. It looks at the
IUIDropSession
to determine whether or not the drop should proceed, proposing (with aUIDropProposal
containing aUIDropOperation
) to move the dropped data, copy the dropped data, cancel the drop, or forbid the drop.In this example,
LocalObject
(set up inGetItemsForBeginningSession
) provides an easy way to determine whether or not the dragged number is even or odd. A copy is proposed if the potential drop is valid, and the drop is forbidden if it is invalid.Proposing a copy or forbidding a drop both add helpful icons to the dragged item:
- An implementation of the
PerformDrop
method from theIUIDropInteractionDelegate
interface extension methods:[Export("dropInteraction:performDrop:")] public void PerformDrop(UIDropInteraction interaction, IUIDropSession session) { var label = interaction == oddDropInteraction ? OddNumbersLabel : EvenNumbersLabel; session.LoadObjects(strings => { if (String.IsNullOrEmpty(label.Text)) { label.Text = strings[0]; } else { label.Text = $"{strings[0]}, {label.Text}"; } }); GenerateNumber(); }
This method is used for dropping numbers on both the even bucket and the odd bucket. The drop target is determined by checking the identity of the passed-in drop interaction.
- Lastly, the
LoadObjects
method onIUIDropSession
fetches the data and adds it to the even or odd bucket.
Learn More
This post only scratches the surface of the iOS 11 drag and drop APIs. To dig deeper, check out the following resources:
- Xamarin documentation about Drag and Drop in iOS 11
- Drag and Drop CollectionView sample
- Drag and Drop Custom View sample
- Drag and Drop TableView sample
- Mastering Drag and Drop in iOS 11 sample
Have questions or comments about this post? Discuss them in the Xamarin forums!
0 comments