{"id":36361,"date":"2018-04-13T13:07:17","date_gmt":"2018-04-13T20:07:17","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=36361"},"modified":"2019-04-04T07:47:26","modified_gmt":"2019-04-04T14:47:26","slug":"drag-and-drop-apis-for-xamarin-apps","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/drag-and-drop-apis-for-xamarin-apps\/","title":{"rendered":"Using the iOS 11 Drag and Drop APIs in Xamarin.iOS Apps"},"content":{"rendered":"<p>\t\t\t\tiOS 11 introduced <a href=\"https:\/\/docs.microsoft.com\/en-us\/xamarin\/ios\/platform\/introduction-to-ios11\/drag-and-drop\">drag and drop<\/a>, a feature that allows users to easily move or copy data within or between apps. With drag and drop, users can:<\/p>\n<ul>\n<li>Select items to drag<\/li>\n<li>Add extra items to a drag after it has started<\/li>\n<li>Transfer data asynchronously between applications<\/li>\n<\/ul>\n<p>On iPads, drag and drop works within or between applications. On iPhones, drag and drop is restricted to a single app.<\/p>\n<h2>Drag and Drop Sample App<\/h2>\n<p>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:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/appimg.gif\" alt=\"The EvenOddNumberDrag sample\" width=\"228\" height=\"443\" class=\"aligncenter size-full wp-image-36404\" title=\"The EvenOddNumberDrag sample\" \/><\/p>\n<p>To follow along, download <a href=\"https:\/\/developer.xamarin.com\/samples\/monotouch\/ios11\/EvenOddNumberDrag\">the code for the EvenOddNumberDrag app<\/a>.<\/p>\n<h3>Enable User Interaction<\/h3>\n<p>Three elements of the app&#8217;s user interface (found in <b>Main.storyboard<\/b>) are relevant to dragging and dropping:<\/p>\n<ol>\n<li><code>NumberLabel<\/code> displays the number which is to be dragged.<\/li>\n<li><code>EvenNumbersLabel<\/code> is the label on which even numbers should be dropped.<\/li>\n<li><code>OddNumbersLabel<\/code> is the label on which odd numbers should be dropped.<\/li>\n<\/ol>\n<p>Since users will be interacting with these labels, each must have its <a href=\"https:\/\/developer.xamarin.com\/api\/property\/UIKit.UIView.UserInteractionEnabled\/\"><code>UserInteractionEnabled<\/code><\/a> property set to <code>true<\/code>. This is done in <b>ViewController.cs<\/b>:<\/p>\n<pre><code>\nprotected void SetupDragAndDrop()\n{\n   NumberLabel.UserInteractionEnabled = true;\n   EvenNumbersLabel.UserInteractionEnabled = true;\n   OddNumbersLabel.UserInteractionEnabled = true;\n   \/\/ \u2026\n}\n<\/code><\/pre>\n<h3>Enable Dragging<\/h3>\n<p>A basic drag interaction requires only a few pieces:<\/p>\n<ul>\n<li>A <a href=\"https:\/\/developer.xamarin.com\/api\/type\/UIKit.UIDragInteraction\/\"><code>UIDragInteraction<\/code><\/a> object that is attached to the view that will be draggable and explicitly enabled:\n<pre><code>\nprotected void SetupDragAndDrop()\n{\n    \/\/ \u2026\n    var numberDragInteraction = new UIDragInteraction(this);\n    NumberLabel.AddInteraction(numberDragInteraction);\t\t\n\n    \/\/ On iPad, this defaults to true. On iPhone, this defaults to \n    \/\/ false. Since this app should work on the iPhone, enable the \n    \/\/ drag interaction.\n    numberDragInteraction.Enabled = true;\n    \/\/ \u2026\n}\n<\/code><\/pre>\n<\/li>\n<li>An <a href=\"https:\/\/developer.xamarin.com\/api\/type\/UIKit.IUIDragInteractionDelegate\/\"><code>IUIDragInteractionDelegate<\/code><\/a> that acts as the delegate for the drag interaction object. In this sample, <code>ViewController<\/code> itself is the <code>IUIDragInteractionDelegate<\/code>. Only one of the delegate methods needs to be implemented:\n<pre><code> \npublic UIDragItem[] GetItemsForBeginningSession(UIDragInteraction interaction, IUIDragSession session) \n{ \n    bool isEven = Convert.ToInt16(NumberLabel.Text) % 2 == 0; \n    var provider = new NSItemProvider(new NSString(NumberLabel.Text)); \n    var item = new UIDragItem(provider) \n    { \n        LocalObject = new NSNumber(isEven) \n    }; \n    return new UIDragItem[] { item } ; \n} \n<\/code><\/pre>\n<p>This method returns an array of <a href=\"https:\/\/developer.xamarin.com\/api\/type\/UIKit.UIDragItem\/\"><code>UIDragItem<\/code><\/a> objects, each representing a piece of data to be included in the drag and drop operation. Each drag item contains an <a href=\"https:\/\/developer.xamarin.com\/api\/type\/Foundation.NSItemProvider\/\"><code>NSItemProvider<\/code><\/a> that holds a representation of the data to be transferred.<\/p>\n<p>In this case, the <code>NSItemProvider<\/code> is given an <a href=\"https:\/\/developer.xamarin.com\/api\/type\/Foundation.NSString\/\"><code>NSString<\/code><\/a>, which implements the <a href=\"https:\/\/developer.xamarin.com\/api\/type\/Foundation.INSItemProviderWriting\/\"><code>INSItemProviderWriting<\/code><\/a> interface, one of the data representations supported by <code>NSItemProvider<\/code>.<\/p>\n<p>The <code>UIDragItem<\/code> has a <a href=\"https:\/\/developer.xamarin.com\/api\/property\/UIKit.UIDragItem.LocalObject\/\"><code>LocalObject<\/code><\/a> property that is accessible only within the application that initiated the drag. Since this example focuses on a single app, for convenience <a href=\"https:\/\/developer.xamarin.com\/api\/member\/UIKit.UIDragInteractionDelegate.GetItemsForBeginningSession\/p\/UIKit.UIDragInteraction\/UIKit.IUIDragSession\/\"><code>GetItemsForBeginningSession<\/code><\/a> sets the <code>LocalObject<\/code> to a <a href=\"https:\/\/developer.xamarin.com\/api\/type\/Foundation.NSNumber\/\"><code>NSNumber<\/code><\/a>. This represents whether or not the dragged number is even.\n<\/li>\n<\/ul>\n<h3>Enable Dropping<\/h3>\n<p>To enable a drop interaction, you will need:<\/p>\n<ul>\n<li>A <a href=\"https:\/\/developer.xamarin.com\/api\/type\/UIKit.UIDropInteraction\/\"><code>UIDropInteraction<\/code><\/a> object for each view on which items can be dropped:\n<pre><code>\nprotected void SetupDragAndDrop()\n{\n    \/\/ \u2026\n    evenDropInteraction = new UIDropInteraction(this);\n    EvenNumbersLabel.AddInteraction(evenDropInteraction);\n    oddDropInteraction = new UIDropInteraction(this);\n    OddNumbersLabel.AddInteraction(oddDropInteraction);\n}\n<\/code><\/pre>\n<\/li>\n<li>An <a href=\"https:\/\/developer.xamarin.com\/api\/type\/UIKit.IUIDropInteractionDelegate\/\"><code>IUIDropInteractionDelegate<\/code><\/a> object. In this sample, <code>ViewController<\/code> serves as the drop delegate.\n<\/li>\n<li>An implementation of the <a href=\"https:\/\/developer.xamarin.com\/api\/member\/UIKit.UIDropInteractionDelegate_Extensions.SessionDidUpdate\/p\/UIKit.IUIDropInteractionDelegate\/UIKit.UIDropInteraction\/UIKit.IUIDropSession\/\"><code>SessionDidUpdate<\/code><\/a> method from the <code>IUIDropInteractionDelegate<\/code> interface <a href=\"https:\/\/developer.xamarin.com\/api\/type\/UIKit.UIDropInteractionDelegate_Extensions\/\">extension methods<\/a>:\n<pre><code>    \n    [Export(\"dropInteraction:sessionDidUpdate:\")] \n    public UIDropProposal SessionDidUpdate(UIDropInteraction interaction, IUIDropSession session) \n    { \n        UIDropProposal proposal; \n        var isEven = (session.Items[0].LocalObject as NSNumber).BoolValue; \n        if (interaction == oddDropInteraction &amp;&amp; !isEven) \n        { \n            proposal = new UIDropProposal(UIDropOperation.Copy); \n        } \n        else if (interaction == evenDropInteraction &amp;&amp; isEven) \n        { \n            proposal = new UIDropProposal(UIDropOperation.Copy); \n        } \n        else \n        { \n            proposal = new UIDropProposal(UIDropOperation.Forbidden);\n        }\n        return proposal;\n    }\n    <\/code><\/pre>\n<p>This method is called any time there&#8217;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 <a href=\"https:\/\/developer.xamarin.com\/api\/type\/UIKit.IUIDropSession\/\"><code>IUIDropSession<\/code><\/a> to determine whether or not the drop should proceed, proposing (with a <a href=\"https:\/\/developer.xamarin.com\/api\/type\/UIKit.UIDropProposal\/\"><code>UIDropProposal<\/code><\/a> containing a <a href=\"https:\/\/developer.xamarin.com\/api\/type\/UIKit.UIDropOperation\/\"><code>UIDropOperation<\/code><\/a>) to move the dropped data, copy the dropped data, cancel the drop, or forbid the drop. <\/p>\n<p>In this example, <code>LocalObject<\/code> (set up in <code>GetItemsForBeginningSession<\/code>) 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.<\/p>\n<p>Proposing a copy or forbidding a drop both add helpful icons to the dragged item:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/dropicons.png\" alt=\"Drop indicators\" width=\"774\" height=\"124\" class=\"aligncenter size-full wp-image-36405\" title=\"Drop indicators\" \/><\/p>\n<\/li>\n<li>An implementation of the <a href=\"https:\/\/developer.xamarin.com\/api\/member\/UIKit.UIDropInteractionDelegate_Extensions.PerformDrop\/p\/UIKit.IUIDropInteractionDelegate\/UIKit.UIDropInteraction\/UIKit.IUIDropSession\/\"><code>PerformDrop<\/code><\/a> method from the <code>IUIDropInteractionDelegate<\/code> interface extension methods:\n<pre><code>\n[Export(\"dropInteraction:performDrop:\")]\npublic void PerformDrop(UIDropInteraction interaction, IUIDropSession session)\n{\n    var label = interaction == oddDropInteraction ? OddNumbersLabel : EvenNumbersLabel;\n    session.LoadObjects(strings =&gt;\n    {\n        if (String.IsNullOrEmpty(label.Text))\n        {\n            label.Text = strings[0];\n        }\n        else\n        {\n            label.Text = $\"{strings[0]}, {label.Text}\";\n        }\n    });\n    GenerateNumber();\n}\n<\/code><\/pre>\n<p>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. <\/p>\n<li>Lastly, the <a href=\"https:\/\/developer.xamarin.com\/api\/member\/UIKit.IUIDropSession.LoadObjects\/\"><code>LoadObjects<\/code><\/a> method on <code>IUIDropSession<\/code> fetches the data and adds it to the even or odd bucket.<\/li>\n<\/ul>\n<h2>Learn More<\/h2>\n<p>This post only scratches the surface of the iOS 11 drag and drop APIs. To dig deeper, check out the following resources:<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.microsoft.com\/xamarin\/ios\/platform\/introduction-to-ios11\/drag-and-drop\">Xamarin documentation about Drag and Drop in iOS 11<\/a><\/li>\n<li><a href=\"https:\/\/developer.xamarin.com\/samples\/monotouch\/ios11\/DragAndDropCollectionView\/\">Drag and Drop CollectionView sample<\/a><\/li>\n<li><a href=\"https:\/\/developer.xamarin.com\/samples\/monotouch\/ios11\/DragAndDropCustomView\/\">Drag and Drop Custom View sample<\/a><\/li>\n<li><a href=\"https:\/\/developer.xamarin.com\/samples\/monotouch\/ios11\/DragAndDropTableView\/\">Drag and Drop TableView sample<\/a><\/li>\n<li><a href=\"https:\/\/developer.xamarin.com\/samples\/monotouch\/ios11\/DragAndDropMastering\/\">Mastering Drag and Drop in iOS 11 sample<\/a><\/li>\n<\/ul>\n<p>Have questions or comments about this post? <a href=\"https:\/\/forums.xamarin.com\/125405\/using-the-ios-11-drag-and-drop-apis-in-xamarin-ios-apps\/\">Discuss them in the Xamarin forums!<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":567,"featured_media":39167,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[6],"class_list":["post-36361","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-ios"],"acf":[],"blog_post_summary":"<p>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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/36361","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/567"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=36361"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/36361\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/39167"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=36361"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=36361"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=36361"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}