Skip to content

Instantly share code, notes, and snippets.

@wbroek
Forked from Cedrick84/FocusTextView.swift
Created March 8, 2016 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wbroek/bd60519804ee9ac64037 to your computer and use it in GitHub Desktop.
Save wbroek/bd60519804ee9ac64037 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

add this to adapt to layout changes

override func layoutSubviews() {
    super.layoutSubviews()
    blurEffectView.frame = bounds.insetBy(dx: -10, dy: -10)
}

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