Here is how to add a mouse hover effect / UIPointer Interactions to your UITableViewCell, UICollectionViewCell, UIButton, UIView using Swift

As Apple describes Pointer Interactions in it’s support document:

Pointer Interactions: Support pointer interactions in your custom controls and views.

iPadOS 13.4 introduces dynamic pointer effects and behaviors that enhance the experience of using an external input device, like a trackpad or mouse, with iPad. As people use an input device, iPadOS automatically adapts the pointer to the current context, providing rich visual feedback and just the right level of precision needed to enhance productivity and simplify common tasks.

Note: UIPointer Interaction is only related to iPad / iPadOS app

Initial Step: Add ‘UIPointerInteractionDelegate’ in your View Controller’s Class Declaration

For UIButton:

Out of Box Implementation:

button.isPointerInteractionEnabled = true

UIView and Custom Implementation for UIButton:

if #available(iOS 13.4, *) {
  customPointerInteraction(on: myButton, pointerInteractionDelegate: self)
}
// 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
}

For UITableViewCell:

Add following code in your UITableViewController’s File

// MARK: - UIPointerInteractionDelegate

    @available(iOS 13.4, *)
    func customPointerInteraction(on view: UITableViewCell, 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?
        print("pointerInteraction view", interaction.view!)
        if let interactionView = interaction.view {
            let targetedPreview = UITargetedPreview(view: interactionView)
            pointerStyle = UIPointerStyle(effect: UIPointerEffect.hover(targetedPreview, preferredTintMode: .overlay, prefersShadow: true, prefersScaledContent: true))
        }
        return pointerStyle
    }
    
    @available(iOS 13.4, *)
        func pointerInteraction(_ interaction: UIPointerInteraction, willEnter region: UIPointerRegion, animator: UIPointerInteractionAnimating) {
        if let interactionView = interaction.view {
            animator.addAnimations {
                interactionView.alpha = 0.5
            }
        }
    }

    @available(iOS 13.4, *)
    func pointerInteraction(_ interaction: UIPointerInteraction, willExit region: UIPointerRegion, animator: UIPointerInteractionAnimating) {
        if let interactionView = interaction.view {
            animator.addAnimations {
                interactionView.alpha = 1.0
            }
        }
    }

Now Add this code to ‘UITableView cellForRowAt indexPath’ Code Block:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath)

        // Configure the cell...
        
        if #available(iOS 13.4, *) {
            customPointerInteraction(on: cell.self, pointerInteractionDelegate: self)
        }

    return cell

    }

For UICollectionView:

Add following code in your UICollectionViewController’s File

// MARK: - UIPointerInteractionDelegate

    @available(iOS 13.4, *)
    func customPointerInteraction(on view: UICollectionViewCell, 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?
        print("pointerInteraction view", interaction.view!)
        if let interactionView = interaction.view {
            let targetedPreview = UITargetedPreview(view: interactionView)
            pointerStyle = UIPointerStyle(effect: UIPointerEffect.hover(targetedPreview, preferredTintMode: .overlay, prefersShadow: true, prefersScaledContent: true))
        }
        return pointerStyle
    }
    
    @available(iOS 13.4, *)
        func pointerInteraction(_ interaction: UIPointerInteraction, willEnter region: UIPointerRegion, animator: UIPointerInteractionAnimating) {
        if let interactionView = interaction.view {
            animator.addAnimations {
                interactionView.alpha = 0.5
            }
        }
    }

    @available(iOS 13.4, *)
    func pointerInteraction(_ interaction: UIPointerInteraction, willExit region: UIPointerRegion, animator: UIPointerInteractionAnimating) {
        if let interactionView = interaction.view {
            animator.addAnimations {
                interactionView.alpha = 1.0
            }
        }
    }

Now Add this code to ‘UICollectionView cellForItemAt indexPath’ Code Block:

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = appIconCollectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! yourCollectionViewCell
        
        if #available(iOS 13.4, *) {
            customPointerInteraction(on: cell.self, pointerInteractionDelegate: self)
        }

    return cell

    }

I hope this information helps you get desired effect…

Thanks & Regards
Mandar Apte

Leave a Reply

Your email address will not be published.