Blog

Of Mice and Mobile devices: Implementing Mouse Interaction in iPadOS 13.4

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.
ownCloud secure cloud solution for filesharing

Mouse Interaction with UIPointerInteraction

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.

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 UIBarButtons,UISegementedControl or UITabBarItem, 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.

UIButton

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.

aButton.isPointerInteractionEnabled = true
UIButton Sample

UIView and Custom Implementation

It is also possible to add an effect to a UIView or a custom pointer style for an UIButton. The implementation requires only need a few lines of code:

Add the Delegate protocol to your class

class MyViewController, UIPointerInteractionDelegate

Attach the UIPointerInteraction to the view, which should get you a mouseover effect. This should be done in viewDidLoad of your view controller or in the init method of the view.

if #available(iOS 13.4, *) {
  customPointerInteraction(on: myButton, pointerInteractionDelegate: self)
}

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 UIPointerInteraction which sets the preferred pointer style. There are different pointer effects available, highlighthoverlift and automatic.

// MARK: - UIPointerInteractionDelegate 
@available(iOS 13.4, *)
func customPointerInteraction(on view: UIView, pointerInteractionDelegate:  
UIPointerInteractionDelegate){ 
  let pointerInteraction = UIPointerInteraction(delegate:  
pointerInteractionDelegate) 
  view.addInteraction(pointerInteraction) 
} 
 
@available(iOS 13.4, *) 
func pointerInteraction(_ interaction: UIPointerInteraction, styleFor region: 
UIPointerRegion) -> UIPointerStyle {
  var pointerStyle: UIPointerStyle? 
 
  if let interactionView = interaction.view {
      let targetedPreview = UITargetedPreview(view: interactionView)
      pointerStyle = UIPointerStyle(effect:
UIPointerEffect.highlight(targetedPreview))
  }
  return pointerStyle
}

That’s all!

Hover Effect

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 UITableViewCell or UICollectionViewCell and use UIPointerStyle with hover effect.

UIPointerStyle(effect: UIPointerEffect.hover(targetedPreview,
preferredTintMode: .overlay, prefersShadow: true, prefersScaledContent: true))

The pointer style will be set as mentioned above in the delegate method func pointerInteraction(_ interaction: UIPointerInteraction, styleFor region: UIPointerRegion) -> UIPointerStyle? .

Hover Sample

Custom Pointer Shape

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:

@available(iOS 13.4, *)
func pointerInteraction(_ interaction: UIPointerInteraction, styleFor region:
UIPointerRegion) -> UIPointerStyle? { 
let shape = UIBezierPath() 
shape.move(to: CGPoint(x: 10, y: 6)) 
shape.addLine(to: CGPoint(x: 10, y: 0)) 
shape.addLine(to: CGPoint(x: 6, y: 0)) 
shape.addLine(to: CGPoint(x: 6, y: 6)) 
shape.addLine(to: CGPoint(x: 0, y: 6)) 
shape.addLine(to: CGPoint(x: 0, y: 10)) 
shape.addLine(to: CGPoint(x: 6, y: 10)) 
shape.addLine(to: CGPoint(x: 6, y: 16)) 
shape.addLine(to: CGPoint(x: 10, y: 16)) 
shape.addLine(to: CGPoint(x: 10, y: 10)) 
shape.addLine(to: CGPoint(x: 16, y: 10)) 
shape.addLine(to: CGPoint(x: 16, y: 6)) 
shape.addLine(to: CGPoint(x: 10, y: 6)) 
shape.close() 
  let pointerShape = UIPointerShape.path(shape) 
  return UIPointerStyle(shape: pointerShape) 
}

This code sample gives you a crosshair pointer shape:

Custom Shape

Conclusion

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.

We at ownCloud already implemented UIPointerInteraction in our iOS app. The new version will be availabe soon on the AppStore. Do you want to test it right now? Join our TestFlight beta!

The ownCloud iOS app is open source and the code for UIPointerInteraction implementation can be found in this branch of our repository on GitHub: feature/ipad-pointerinteraction

The complete documentation by Apple is available here: Apple Developer Documentation > UIKit > Pointer Interactions

ownCloud

March 31, 2020

Ready to see what’s next?

Having trouble viewing or submitting this form?

Contact Us

We care about protecting your data. Here’s our Privacy Policy.

Read now:

Go for Enterprise: ownCloud Infinite Scale

Go for Enterprise: ownCloud Infinite Scale

Tim Schürmann, a seasoned IT journalist from Germany, specializes in open source and programming languages. Over the last several years, he has authored many articles on Go, including several related to ownCloud. We sought his expert insights on Go in the context of ownCloud Infinite Scale. Here is his op-ed.

read more