Display focus effects for UITextView on tvOS?

717 Views Asked by At

When focus changes to a UITextView in any of the media apps on Apple TV - App Store, Movies, TV Shows etc. - it highlights with an effect that looks like this:

enter image description here

It pops out, a shadow appears, and rolling your thumb across the trackpad gives it that glossy 3D effect. It's a lot like a focused UIButton, or a UIImageView contained as a subview of a focused view, like a UICollectionViewCell.

With UIButton, if it's initialised with a type of UIButtonType.System, it gains the focused appearance when focused, without any work.

With a UIImageView within a focused view can set adjustsImageWhenAncestorFocused, and upon the view becoming focused, it gains the focused appearance.

But neither UITextView, nor UILabel, are automatically styled upon being selected, or have a property to adjust appearance when ancestor is focused.

So I'm wondering how I'm to do this. Does Apple provide any way to display a focused textview like this?

1

There are 1 best solutions below

1
On

The 'glossy 3D effect' you are describing, as far as I know, is only accessible by using UIImageView.adjustsImageWhenAncestorIsFocused. And is nearly impossible to recreate yourself.

Based on this, I would guess that the effect is achieved by overlaying the view with a UIImage copy of itself on focusing. That, or Apple has access to a low level API for the glossy 3D effect that you and I cannot access.

So, try something like:

class CustomTextView:  
override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
  if (isFocused){
    if (self.imageOverlay != nil) {
    let imageView: UIImageView = self.toImageView() // many ways to achieve this. Ex: see UIGraphicsBeginImageContext()
    imageView.frame = bounds
    imageView.adjustsImageWhenAncestorIsFocused = true
    imageView.clipsToBounds = false
    self.imageOverlay = imageView
    addSubview(imageView)
    }
  }
  else{
    coordinator.addCoordinatedAnimations(... completion:{
      if (!self.isFocused){
        self.imageOverlay.removeFromSuperview()
        self.imageOverlay = nil
      }
    })
  }
  super.didUpdateFocus( in:context, with:coordinator ) 
}

The UIImageView.adjustsImageWhenAncestorIsFocused effect also includes scaling, drop shadow, and feedback/parallax while panning. These are neither removable nor configurable.

As an alternative, try playing with the various lockup views in TVUIKit. Maybe one or more of them have the glossy 3D effect built in as well. I have not experimented with them yet.