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.

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

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, highlight, hover, lift 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? .

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:

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

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close