{"id":2406,"date":"2020-03-31T17:34:34","date_gmt":"2020-03-31T17:34:34","guid":{"rendered":"https:\/\/owncloud.com\/?p=2406"},"modified":"2020-07-07T12:46:40","modified_gmt":"2020-07-07T12:46:40","slug":"of-mice-and-mobile-devices-implementing-mouse-interaction-in-ipados-13-4","status":"publish","type":"post","link":"https:\/\/owncloud.com\/de\/blogs\/of-mice-and-mobile-devices-implementing-mouse-interaction-in-ipados-13-4\/","title":{"rendered":"Of Mice and Mobile devices: Implementing Mouse Interaction in iPadOS 13.4"},"content":{"rendered":"<h2>Mouse Interaction with UIPointerInteraction<\/h2>\n<div class=\"content\">\n<p>Apple released iPadOS 13.4 on March 24th which introduced mouse and trackpad support for the iPad. This means if you connect a bluetooth or USB pointer device to your iPad you have a completly new way to interact with it.<\/p>\n<p>Apple decided not to show a classic cursor. Instead, they reinvented the cursor for the iPad. Instead you will see a circle that, if it gets near a\u00a0<code>UIBarButtons<\/code>,<code>UISegementedControl<\/code>\u00a0or\u00a0<code>UITabBarItem<\/code>, snaps automatically to this element and focuses it. In addition to this, you will get a nice highlight effect. This means a lot of elements of app are working out of the box without an app update.<\/p>\n<h2>UIButton<\/h2>\n<p>Apple added new APIs to add this effect to more UI elements than are supported out of the box. For an UIButton you only have to set a property and you will get the same effect.<\/p>\n<pre class=\"wp-block-preformatted\">aButton.isPointerInteractionEnabled = true<\/pre>\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" class=\"wp-image-20136 aligncenter\" src=\"https:\/\/owncloud.org\/wp-content\/uploads\/2020\/03\/UIButton-Sample.gif\" alt=\"\" \/><\/figure>\n<h2>UIView and Custom Implementation<\/h2>\n<p>It is also possible to add an effect to a\u00a0<code>UIView<\/code>\u00a0or a custom pointer style for an\u00a0<code>UIButton<\/code>. The implementation requires only need a few lines of code:<\/p>\n<p>Add the Delegate protocol to your class<\/p>\n<pre class=\"wp-block-preformatted\">class MyViewController, UIPointerInteractionDelegate<\/pre>\n<p>Attach the\u00a0<code>UIPointerInteraction<\/code>\u00a0to the view, which should get you a mouseover effect. This should be done in\u00a0<code>viewDidLoad<\/code>\u00a0of your view controller or in the\u00a0<code>init<\/code>\u00a0method of the view.<\/p>\n<pre class=\"wp-block-preformatted\">if #available(iOS 13.4, *) {\r\n\u00a0\u00a0customPointerInteraction(on: myButton, pointerInteractionDelegate: self)\r\n}<\/pre>\n<p>Last but not least add this block to your class. It includes the function for adding the pointer interaction to the view and the delegate method for the\u00a0<code>UIPointerInteraction<\/code>\u00a0which sets the preferred pointer style. There are different pointer effects available,\u00a0<code>highlight<\/code>,\u00a0<code>hover<\/code>,\u00a0<code>lift<\/code>\u00a0and\u00a0<code>automatic<\/code>.<\/p>\n<pre class=\"wp-block-preformatted\">\/\/ MARK: - UIPointerInteractionDelegate \r\n@available(iOS 13.4, *)\r\nfunc customPointerInteraction(on view: UIView, pointerInteractionDelegate:  \r\nUIPointerInteractionDelegate){ \r\n\u00a0\u00a0let pointerInteraction = UIPointerInteraction(delegate:  \r\npointerInteractionDelegate) \r\n\u00a0\u00a0view.addInteraction(pointerInteraction) \r\n} \r\n \r\n@available(iOS 13.4, *) \r\nfunc pointerInteraction(_ interaction: UIPointerInteraction, styleFor region: \r\nUIPointerRegion) -&gt; UIPointerStyle {\r\n\u00a0\u00a0var pointerStyle: UIPointerStyle? \r\n \r\n\u00a0\u00a0if let interactionView = interaction.view {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0let targetedPreview = UITargetedPreview(view: interactionView)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0pointerStyle = UIPointerStyle(effect:\r\nUIPointerEffect.highlight(targetedPreview))\r\n\u00a0\u00a0}\r\n\u00a0\u00a0return pointerStyle\r\n}<\/pre>\n<p>That\u2019s all!<\/p>\n<h2>Hover Effect<\/h2>\n<p>If you want to give your table views, rows and collection view cells a hover effect, you can use the same implementation as above, but set the interaction to your\u00a0<code>UITableViewCell<\/code>\u00a0or\u00a0<code>UICollectionViewCell<\/code>\u00a0and use\u00a0<code>UIPointerStyle<\/code>\u00a0with hover effect.<\/p>\n<pre class=\"wp-block-preformatted\">UIPointerStyle(effect: UIPointerEffect.hover(targetedPreview,\r\npreferredTintMode: .overlay, prefersShadow: true, prefersScaledContent: true))<\/pre>\n<p>The pointer style will be set as mentioned above in the delegate method\u00a0<code>func pointerInteraction(_ interaction: UIPointerInteraction, styleFor region: UIPointerRegion) -&gt; UIPointerStyle?<\/code>\u00a0.<\/p>\n<p class=\"wp-block-image size-large\"><img decoding=\"async\" class=\"wp-image-20163 aligncenter\" src=\"https:\/\/owncloud.org\/wp-content\/uploads\/2020\/03\/Hover-Sample.gif\" alt=\"\" \/><\/p>\n<h2>Custom Pointer Shape<\/h2>\n<p>You can also change the shape of the pointer and implement a custom pointer style for when hovering on a UI element by setting an bezier path:<\/p>\n<pre class=\"wp-block-preformatted\">@available(iOS 13.4, *)\r\nfunc pointerInteraction(_ interaction: UIPointerInteraction, styleFor region:\r\nUIPointerRegion) -&gt; UIPointerStyle? { \r\nlet shape = UIBezierPath() \r\nshape.move(to: CGPoint(x: 10, y: 6)) \r\nshape.addLine(to: CGPoint(x: 10, y: 0)) \r\nshape.addLine(to: CGPoint(x: 6, y: 0)) \r\nshape.addLine(to: CGPoint(x: 6, y: 6)) \r\nshape.addLine(to: CGPoint(x: 0, y: 6)) \r\nshape.addLine(to: CGPoint(x: 0, y: 10)) \r\nshape.addLine(to: CGPoint(x: 6, y: 10)) \r\nshape.addLine(to: CGPoint(x: 6, y: 16)) \r\nshape.addLine(to: CGPoint(x: 10, y: 16)) \r\nshape.addLine(to: CGPoint(x: 10, y: 10)) \r\nshape.addLine(to: CGPoint(x: 16, y: 10)) \r\nshape.addLine(to: CGPoint(x: 16, y: 6)) \r\nshape.addLine(to: CGPoint(x: 10, y: 6)) \r\nshape.close() \r\n  let pointerShape = UIPointerShape.path(shape) \r\n  return UIPointerStyle(shape: pointerShape) \r\n}<\/pre>\n<p>This code sample gives you a crosshair pointer shape:<\/p>\n<p class=\"wp-block-image size-large\"><img decoding=\"async\" class=\"wp-image-20168 aligncenter\" src=\"https:\/\/owncloud.org\/wp-content\/uploads\/2020\/03\/Custom-Shape.gif\" alt=\"\" \/><\/p>\n<h2>Conclusion<\/h2>\n<p>As of iPadOS 13.4, developers can upgrade their apps to support pointing devices on the iPad and create a user experience that rivals that of desktop apps.<\/p>\n<p>We at ownCloud already implemented\u00a0<code>UIPointerInteraction<\/code>\u00a0in our iOS app. The new version will be availabe soon on the AppStore. Do you want to test it right now? <a class=\"button-oc\" href=\"https:\/\/testflight.apple.com\/join\/Oktj0iKv\" target=\"_blank\" rel=\"noopener\">Join our TestFlight beta!<\/a><\/p>\n<p>The ownCloud iOS app is open source and the code for\u00a0<code>UIPointerInteraction<\/code>\u00a0implementation can be found in this branch of our repository on GitHub:\u00a0<a href=\"https:\/\/github.com\/owncloud\/ios-app\/tree\/feature\/ipad-pointerinteraction\" target=\"_blank\" rel=\"noopener\">feature\/ipad-pointerinteraction<\/a><\/p>\n<p>The complete documentation by Apple is available here:\u00a0<a href=\"https:\/\/developer.apple.com\/documentation\/uikit\/pointer_interactions?changes=latest_minor&amp;language=objc\" target=\"_blank\" rel=\"noopener\">Apple Developer Documentation &gt; UIKit &gt; Pointer Interactions<\/a><\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Recently, Apple thoroughly improved mouse and trackpad support for the iPad. ownCloud for iOS is one of the first major Apps to support this feature, and we proudly publish the implementation for others to get up to speed quickly.<\/p>\n","protected":false},"author":7,"featured_media":78665,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","inline_featured_image":false,"footnotes":""},"categories":[43],"tags":[],"class_list":["post-2406","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"acf":[],"_links":{"self":[{"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/posts\/2406","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/comments?post=2406"}],"version-history":[{"count":0,"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/posts\/2406\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/media\/78665"}],"wp:attachment":[{"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/media?parent=2406"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/categories?post=2406"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/owncloud.com\/de\/wp-json\/wp\/v2\/tags?post=2406"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}