Skip to content

Instantly share code, notes, and snippets.

@Cedrick84
Last active July 21, 2020 10:33
Show Gist options
  • Save Cedrick84/8922a0af730c39c05794 to your computer and use it in GitHub Desktop.
Save Cedrick84/8922a0af730c39c05794 to your computer and use it in GitHub Desktop.
// TextView subclass that replicates TVOS movies app
// Also made a quick presentation controller
// Just connect the delegate to the ViewController in IB
// and set the TextView class to FocusTextView
import UIKit
class TextPresentationViewController:UIViewController {
let label = UILabel()
let blurStyle = UIBlurEffectStyle.Dark
override func viewDidLoad() {
let blurEffect = UIBlurEffect(style: blurStyle)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = view.bounds
view.addSubview(blurEffectView)
let vibrancyEffect = UIVibrancyEffect(forBlurEffect: blurEffect)
let vibrancyEffectView = UIVisualEffectView(effect: vibrancyEffect)
view.addSubview(vibrancyEffectView)
vibrancyEffectView.addSubview(label)
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
view.addConstraints([
NSLayoutConstraint(item: label, attribute: .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 0.5, constant: 0),
NSLayoutConstraint(item: label, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0),
NSLayoutConstraint(item: label, attribute: .CenterY, relatedBy: .Equal, toItem: view, attribute: .CenterY, multiplier: 1, constant: 0)])
}
}
class FocusTextView: UITextView {
private let blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .ExtraLight))
private let motionEffectGroup = UIMotionEffectGroup()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
selectable = true
scrollEnabled = false
clipsToBounds = false
textContainer.lineBreakMode = .ByTruncatingTail
textContainerInset = UIEdgeInsetsZero;
blurEffectView.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.6)
blurEffectView.frame = CGRectInset(bounds, -10, -10)
blurEffectView.alpha = 0
blurEffectView.layer.cornerRadius = 10
blurEffectView.clipsToBounds = true
insertSubview(blurEffectView, atIndex: 0)
let tap = UITapGestureRecognizer(target: self, action: "tapped:")
tap.allowedPressTypes = [NSNumber(integer: UIPressType.Select.rawValue)]
addGestureRecognizer(tap)
let motionRange = 5
let verticalMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.y", type: .TiltAlongVerticalAxis)
verticalMotionEffect.minimumRelativeValue = -motionRange
verticalMotionEffect.maximumRelativeValue = motionRange
let tiltAngle = CGFloat(2 * M_PI / 180)
var minX = CATransform3DIdentity
minX.m34 = 1.0 / 500
minX = CATransform3DRotate(minX, -tiltAngle, 1, 0, 0)
var maxX = CATransform3DIdentity
maxX.m34 = minX.m34
maxX = CATransform3DRotate(maxX, tiltAngle, 1, 0, 0)
let verticalTiltEffect = UIInterpolatingMotionEffect(keyPath: "layer.transform", type: .TiltAlongVerticalAxis)
verticalTiltEffect.minimumRelativeValue = NSValue(CATransform3D: minX)
verticalTiltEffect.maximumRelativeValue = NSValue(CATransform3D: maxX)
self.motionEffectGroup.motionEffects = [verticalMotionEffect, verticalTiltEffect]
}
func tapped(gesture: UITapGestureRecognizer) {
if let vc = delegate as? UIViewController {
let modal = TextPresentationViewController()
modal.label.attributedText = attributedText
modal.label.textColor = .whiteColor()
modal.modalPresentationStyle = .OverFullScreen
vc.presentViewController(modal, animated: true, completion: nil)
}
}
override func canBecomeFocused() -> Bool {
return true
}
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
if context.nextFocusedView == self {
coordinator.addCoordinatedAnimations({ () -> Void in
self.blurEffectView.alpha = 1
self.addMotionEffect(self.motionEffectGroup)
}, completion: nil)
} else if context.previouslyFocusedView == self {
coordinator.addCoordinatedAnimations({ () -> Void in
self.blurEffectView.alpha = 0
self.removeMotionEffect(self.motionEffectGroup)
}, completion: nil)
}
}
}
@ninokierulf
Copy link

ninokierulf commented Feb 28, 2017

swift 3.0


import UIKit

class FocusTextView: UITextView {
    
    private let blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .extraLight))
    
    private let motionEffectGroup = UIMotionEffectGroup()
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        isSelectable = true
        isScrollEnabled = false
        clipsToBounds = false
        textContainer.lineBreakMode = .byTruncatingTail
        textContainerInset = .zero;
        
        blurEffectView.backgroundColor = UIColor.white.withAlphaComponent(0.6)
        blurEffectView.frame = bounds.insetBy(dx: -10, dy: -10)
        blurEffectView.alpha = 0
        blurEffectView.layer.cornerRadius = 10
        blurEffectView.clipsToBounds = true
        insertSubview(blurEffectView, at: 0)
        
        let tap = UITapGestureRecognizer(target: self, action: #selector(tapped))
        
        tap.allowedPressTypes = [NSNumber(value: UIPressType.select.rawValue)]
        addGestureRecognizer(tap)
        
        let motionRange = 5
        
        let verticalMotionEffect = UIInterpolatingMotionEffect(keyPath: "center.y", type: .tiltAlongVerticalAxis)
        verticalMotionEffect.minimumRelativeValue = -motionRange
        verticalMotionEffect.maximumRelativeValue = motionRange
        
        let tiltAngle = CGFloat(1 * M_PI / 180)
        
        var minX = CATransform3DIdentity
        minX.m34 = 1.0 / 500
        minX = CATransform3DRotate(minX, -tiltAngle, 1, 0, 0)
        
        var maxX = CATransform3DIdentity
        maxX.m34 = minX.m34
        maxX = CATransform3DRotate(maxX, tiltAngle, 1, 0, 0)
        
        let verticalTiltEffect = UIInterpolatingMotionEffect(keyPath: "layer.transform", type: .tiltAlongVerticalAxis)
        verticalTiltEffect.minimumRelativeValue =  NSValue(caTransform3D: minX)
        verticalTiltEffect.maximumRelativeValue =  NSValue(caTransform3D: maxX)
        
        self.motionEffectGroup.motionEffects = [verticalMotionEffect, verticalTiltEffect]
    }
    
    func tapped(_ gestureRecognizer: UITapGestureRecognizer) {
        
        if let vc = delegate as? UIViewController {
            let modal = TextPresentationViewController()
            modal.label.attributedText = attributedText
            modal.label.textColor = .white
            modal.modalPresentationStyle = .overFullScreen
            vc.present(modal, animated: true, completion: nil)
        }
    }
    
    override var canBecomeFocused: Bool {
        return true
    }
    
    
    override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
        
        if context.nextFocusedView == self {
            coordinator.addCoordinatedAnimations({ () -> Void in
                self.blurEffectView.alpha = 1
                self.addMotionEffect(self.motionEffectGroup)
            }, completion: nil)
        } else if context.previouslyFocusedView == self {
            coordinator.addCoordinatedAnimations({ () -> Void in
                self.blurEffectView.alpha = 0
                self.removeMotionEffect(self.motionEffectGroup)
            }, completion: nil)
        }
    }
}

class TextPresentationViewController:UIViewController {
    let label = UILabel()
    let blurStyle = UIBlurEffectStyle.dark
    
    override func viewDidLoad() {
        
        let blurEffect = UIBlurEffect(style: blurStyle)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.frame = view.bounds
        view.addSubview(blurEffectView)
        

        let vibrancyEffect = UIVibrancyEffect(blurEffect: blurEffect)
        let vibrancyEffectView = UIVisualEffectView(effect: vibrancyEffect)
        view.addSubview(vibrancyEffectView)
        
        vibrancyEffectView.addSubview(label)
        
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        
        label.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5).isActive = true
        label.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 1.0).isActive = true
        label.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 1.0).isActive = true
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment