634 lines
22 KiB
Swift
634 lines
22 KiB
Swift
//
|
|
// UIViewExtensions.swift
|
|
// EZSwiftExtensions
|
|
//
|
|
// Created by Goktug Yilmaz on 15/07/15.
|
|
// Copyright (c) 2015 Goktug Yilmaz. All rights reserved.
|
|
//
|
|
|
|
#if os(iOS) || os(tvOS)
|
|
|
|
import UIKit
|
|
|
|
// MARK: Custom UIView Initilizers
|
|
extension UIView {
|
|
/// EZSE: convenience contructor to define a view based on width, height and base coordinates.
|
|
@objc public convenience init(x: CGFloat, y: CGFloat, w: CGFloat, h: CGFloat) {
|
|
self.init(frame: CGRect(x: x, y: y, width: w, height: h))
|
|
}
|
|
|
|
/// EZSE: puts padding around the view
|
|
public convenience init(superView: UIView, padding: CGFloat) {
|
|
self.init(frame: CGRect(x: superView.x + padding, y: superView.y + padding, width: superView.w - padding*2, height: superView.h - padding*2))
|
|
}
|
|
|
|
/// EZSwiftExtensions - Copies size of superview
|
|
public convenience init(superView: UIView) {
|
|
self.init(frame: CGRect(origin: CGPoint.zero, size: superView.size))
|
|
}
|
|
}
|
|
|
|
// MARK: Frame Extensions
|
|
extension UIView {
|
|
|
|
/// EZSE: add multiple subviews
|
|
public func addSubviews(_ views: [UIView]) {
|
|
views.forEach { [weak self] eachView in
|
|
self?.addSubview(eachView)
|
|
}
|
|
}
|
|
|
|
//TODO: Add pics to readme
|
|
/// EZSE: resizes this view so it fits the largest subview
|
|
public func resizeToFitSubviews() {
|
|
var width: CGFloat = 0
|
|
var height: CGFloat = 0
|
|
for someView in self.subviews {
|
|
let aView = someView
|
|
let newWidth = aView.x + aView.w
|
|
let newHeight = aView.y + aView.h
|
|
width = max(width, newWidth)
|
|
height = max(height, newHeight)
|
|
}
|
|
frame = CGRect(x: x, y: y, width: width, height: height)
|
|
}
|
|
|
|
/// EZSE: resizes this view so it fits the largest subview
|
|
public func resizeToFitSubviews(_ tagsToIgnore: [Int]) {
|
|
var width: CGFloat = 0
|
|
var height: CGFloat = 0
|
|
for someView in self.subviews {
|
|
let aView = someView
|
|
if !tagsToIgnore.contains(someView.tag) {
|
|
let newWidth = aView.x + aView.w
|
|
let newHeight = aView.y + aView.h
|
|
width = max(width, newWidth)
|
|
height = max(height, newHeight)
|
|
}
|
|
}
|
|
frame = CGRect(x: x, y: y, width: width, height: height)
|
|
}
|
|
|
|
/// EZSE: resizes this view so as to fit its width.
|
|
public func resizeToFitWidth() {
|
|
let currentHeight = self.h
|
|
self.sizeToFit()
|
|
self.h = currentHeight
|
|
}
|
|
|
|
/// EZSE: resizes this view so as to fit its height.
|
|
public func resizeToFitHeight() {
|
|
let currentWidth = self.w
|
|
self.sizeToFit()
|
|
self.w = currentWidth
|
|
}
|
|
|
|
/// EZSE: getter and setter for the x coordinate of the frame's origin for the view.
|
|
public var x: CGFloat {
|
|
get {
|
|
return self.frame.origin.x
|
|
} set(value) {
|
|
self.frame = CGRect(x: value, y: self.y, width: self.w, height: self.h)
|
|
}
|
|
}
|
|
|
|
/// EZSE: getter and setter for the y coordinate of the frame's origin for the view.
|
|
public var y: CGFloat {
|
|
get {
|
|
return self.frame.origin.y
|
|
} set(value) {
|
|
self.frame = CGRect(x: self.x, y: value, width: self.w, height: self.h)
|
|
}
|
|
}
|
|
|
|
/// EZSE: variable to get the width of the view.
|
|
public var w: CGFloat {
|
|
get {
|
|
return self.frame.size.width
|
|
} set(value) {
|
|
self.frame = CGRect(x: self.x, y: self.y, width: value, height: self.h)
|
|
}
|
|
}
|
|
|
|
/// EZSE: variable to get the height of the view.
|
|
public var h: CGFloat {
|
|
get {
|
|
return self.frame.size.height
|
|
} set(value) {
|
|
self.frame = CGRect(x: self.x, y: self.y, width: self.w, height: value)
|
|
}
|
|
}
|
|
|
|
/// EZSE: getter and setter for the x coordinate of leftmost edge of the view.
|
|
public var left: CGFloat {
|
|
get {
|
|
return self.x
|
|
} set(value) {
|
|
self.x = value
|
|
}
|
|
}
|
|
|
|
/// EZSE: getter and setter for the x coordinate of the rightmost edge of the view.
|
|
public var right: CGFloat {
|
|
get {
|
|
return self.x + self.w
|
|
} set(value) {
|
|
self.x = value - self.w
|
|
}
|
|
}
|
|
|
|
/// EZSE: getter and setter for the y coordinate for the topmost edge of the view.
|
|
public var top: CGFloat {
|
|
get {
|
|
return self.y
|
|
} set(value) {
|
|
self.y = value
|
|
}
|
|
}
|
|
|
|
/// EZSE: getter and setter for the y coordinate of the bottom most edge of the view.
|
|
public var bottom: CGFloat {
|
|
get {
|
|
return self.y + self.h
|
|
} set(value) {
|
|
self.y = value - self.h
|
|
}
|
|
}
|
|
|
|
/// EZSE: getter and setter the frame's origin point of the view.
|
|
public var origin: CGPoint {
|
|
get {
|
|
return self.frame.origin
|
|
} set(value) {
|
|
self.frame = CGRect(origin: value, size: self.frame.size)
|
|
}
|
|
}
|
|
|
|
/// EZSE: getter and setter for the X coordinate of the center of a view.
|
|
public var centerX: CGFloat {
|
|
get {
|
|
return self.center.x
|
|
} set(value) {
|
|
self.center.x = value
|
|
}
|
|
}
|
|
|
|
/// EZSE: getter and setter for the Y coordinate for the center of a view.
|
|
public var centerY: CGFloat {
|
|
get {
|
|
return self.center.y
|
|
} set(value) {
|
|
self.center.y = value
|
|
}
|
|
}
|
|
|
|
/// EZSE: getter and setter for frame size for the view.
|
|
public var size: CGSize {
|
|
get {
|
|
return self.frame.size
|
|
} set(value) {
|
|
self.frame = CGRect(origin: self.frame.origin, size: value)
|
|
}
|
|
}
|
|
|
|
/// EZSE: getter for an leftwards offset position from the leftmost edge.
|
|
public func leftOffset(_ offset: CGFloat) -> CGFloat {
|
|
return self.left - offset
|
|
}
|
|
|
|
/// EZSE: getter for an rightwards offset position from the rightmost edge.
|
|
public func rightOffset(_ offset: CGFloat) -> CGFloat {
|
|
return self.right + offset
|
|
}
|
|
|
|
/// EZSE: aligns the view to the top by a given offset.
|
|
public func topOffset(_ offset: CGFloat) -> CGFloat {
|
|
return self.top - offset
|
|
}
|
|
|
|
/// EZSE: align the view to the bottom by a given offset.
|
|
public func bottomOffset(_ offset: CGFloat) -> CGFloat {
|
|
return self.bottom + offset
|
|
}
|
|
|
|
//TODO: Add to readme
|
|
/// EZSE: align the view widthwise to the right by a given offset.
|
|
public func alignRight(_ offset: CGFloat) -> CGFloat {
|
|
return self.w - offset
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func reorderSubViews(_ reorder: Bool = false, tagsToIgnore: [Int] = []) -> CGFloat {
|
|
var currentHeight: CGFloat = 0
|
|
for someView in subviews {
|
|
if !tagsToIgnore.contains(someView.tag) && !(someView ).isHidden {
|
|
if reorder {
|
|
let aView = someView
|
|
aView.frame = CGRect(x: aView.frame.origin.x, y: currentHeight, width: aView.frame.width, height: aView.frame.height)
|
|
}
|
|
currentHeight += someView.frame.height
|
|
}
|
|
}
|
|
return currentHeight
|
|
}
|
|
|
|
public func removeSubviews() {
|
|
for subview in subviews {
|
|
subview.removeFromSuperview()
|
|
}
|
|
}
|
|
|
|
/// EZSE: Centers view in superview horizontally
|
|
public func centerXInSuperView() {
|
|
guard let parentView = superview else {
|
|
assertionFailure("EZSwiftExtensions Error: The view \(self) doesn't have a superview")
|
|
return
|
|
}
|
|
|
|
self.x = parentView.w/2 - self.w/2
|
|
}
|
|
|
|
/// EZSE: Centers view in superview vertically
|
|
public func centerYInSuperView() {
|
|
guard let parentView = superview else {
|
|
assertionFailure("EZSwiftExtensions Error: The view \(self) doesn't have a superview")
|
|
return
|
|
}
|
|
|
|
self.y = parentView.h/2 - self.h/2
|
|
}
|
|
|
|
/// EZSE: Centers view in superview horizontally & vertically
|
|
public func centerInSuperView() {
|
|
self.centerXInSuperView()
|
|
self.centerYInSuperView()
|
|
}
|
|
}
|
|
|
|
// MARK: Transform Extensions
|
|
extension UIView {
|
|
/// EZSwiftExtensions
|
|
public func setRotationX(_ x: CGFloat) {
|
|
var transform = CATransform3DIdentity
|
|
transform.m34 = 1.0 / -1000.0
|
|
transform = CATransform3DRotate(transform, x.degreesToRadians(), 1.0, 0.0, 0.0)
|
|
self.layer.transform = transform
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func setRotationY(_ y: CGFloat) {
|
|
var transform = CATransform3DIdentity
|
|
transform.m34 = 1.0 / -1000.0
|
|
transform = CATransform3DRotate(transform, y.degreesToRadians(), 0.0, 1.0, 0.0)
|
|
self.layer.transform = transform
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func setRotationZ(_ z: CGFloat) {
|
|
var transform = CATransform3DIdentity
|
|
transform.m34 = 1.0 / -1000.0
|
|
transform = CATransform3DRotate(transform, z.degreesToRadians(), 0.0, 0.0, 1.0)
|
|
self.layer.transform = transform
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func setRotation(x: CGFloat, y: CGFloat, z: CGFloat) {
|
|
var transform = CATransform3DIdentity
|
|
transform.m34 = 1.0 / -1000.0
|
|
transform = CATransform3DRotate(transform, x.degreesToRadians(), 1.0, 0.0, 0.0)
|
|
transform = CATransform3DRotate(transform, y.degreesToRadians(), 0.0, 1.0, 0.0)
|
|
transform = CATransform3DRotate(transform, z.degreesToRadians(), 0.0, 0.0, 1.0)
|
|
self.layer.transform = transform
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func setScale(x: CGFloat, y: CGFloat) {
|
|
var transform = CATransform3DIdentity
|
|
transform.m34 = 1.0 / -1000.0
|
|
transform = CATransform3DScale(transform, x, y, 1)
|
|
self.layer.transform = transform
|
|
}
|
|
}
|
|
|
|
// MARK: Layer Extensions
|
|
extension UIView {
|
|
/// EZSwiftExtensions
|
|
public func setCornerRadius(radius: CGFloat) {
|
|
self.layer.cornerRadius = radius
|
|
self.layer.masksToBounds = true
|
|
}
|
|
//TODO: add this to readme
|
|
/// EZSwiftExtensions
|
|
public func addShadow(offset: CGSize, radius: CGFloat, color: UIColor, opacity: Float, cornerRadius: CGFloat? = nil) {
|
|
self.layer.shadowOffset = offset
|
|
self.layer.shadowRadius = radius
|
|
self.layer.shadowOpacity = opacity
|
|
self.layer.shadowColor = color.cgColor
|
|
if let r = cornerRadius {
|
|
self.layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: r).cgPath
|
|
}
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func addBorder(width: CGFloat, color: UIColor) {
|
|
layer.borderWidth = width
|
|
layer.borderColor = color.cgColor
|
|
layer.masksToBounds = true
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func addBorderTop(size: CGFloat, color: UIColor) {
|
|
addBorderUtility(x: 0, y: 0, width: frame.width, height: size, color: color)
|
|
}
|
|
|
|
//TODO: add to readme
|
|
/// EZSwiftExtensions
|
|
public func addBorderTopWithPadding(size: CGFloat, color: UIColor, padding: CGFloat) {
|
|
addBorderUtility(x: padding, y: 0, width: frame.width - padding*2, height: size, color: color)
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func addBorderBottom(size: CGFloat, color: UIColor) {
|
|
addBorderUtility(x: 0, y: frame.height - size, width: frame.width, height: size, color: color)
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func addBorderLeft(size: CGFloat, color: UIColor) {
|
|
addBorderUtility(x: 0, y: 0, width: size, height: frame.height, color: color)
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func addBorderRight(size: CGFloat, color: UIColor) {
|
|
addBorderUtility(x: frame.width - size, y: 0, width: size, height: frame.height, color: color)
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
fileprivate func addBorderUtility(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat, color: UIColor) {
|
|
let border = CALayer()
|
|
border.backgroundColor = color.cgColor
|
|
border.frame = CGRect(x: x, y: y, width: width, height: height)
|
|
layer.addSublayer(border)
|
|
}
|
|
//TODO: add this to readme
|
|
/// EZSwiftExtensions
|
|
public func drawCircle(fillColor: UIColor, strokeColor: UIColor, strokeWidth: CGFloat) {
|
|
let path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: self.w, height: self.w), cornerRadius: self.w/2)
|
|
let shapeLayer = CAShapeLayer()
|
|
shapeLayer.path = path.cgPath
|
|
shapeLayer.fillColor = fillColor.cgColor
|
|
shapeLayer.strokeColor = strokeColor.cgColor
|
|
shapeLayer.lineWidth = strokeWidth
|
|
self.layer.addSublayer(shapeLayer)
|
|
}
|
|
//TODO: add this to readme
|
|
/// EZSwiftExtensions
|
|
public func drawStroke(width: CGFloat, color: UIColor) {
|
|
let path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: self.w, height: self.w), cornerRadius: self.w/2)
|
|
let shapeLayer = CAShapeLayer ()
|
|
shapeLayer.path = path.cgPath
|
|
shapeLayer.fillColor = UIColor.clear.cgColor
|
|
shapeLayer.strokeColor = color.cgColor
|
|
shapeLayer.lineWidth = width
|
|
self.layer.addSublayer(shapeLayer)
|
|
}
|
|
}
|
|
|
|
private let UIViewAnimationDuration: TimeInterval = 1
|
|
private let UIViewAnimationSpringDamping: CGFloat = 0.5
|
|
private let UIViewAnimationSpringVelocity: CGFloat = 0.5
|
|
|
|
//TODO: add this to readme
|
|
// MARK: Animation Extensions
|
|
extension UIView {
|
|
/// EZSwiftExtensions
|
|
public func spring(animations: @escaping (() -> Void), completion: ((Bool) -> Void)? = nil) {
|
|
spring(duration: UIViewAnimationDuration, animations: animations, completion: completion)
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func spring(duration: TimeInterval, animations: @escaping (() -> Void), completion: ((Bool) -> Void)? = nil) {
|
|
UIView.animate(
|
|
withDuration: UIViewAnimationDuration,
|
|
delay: 0,
|
|
usingSpringWithDamping: UIViewAnimationSpringDamping,
|
|
initialSpringVelocity: UIViewAnimationSpringVelocity,
|
|
options: UIViewAnimationOptions.allowAnimatedContent,
|
|
animations: animations,
|
|
completion: completion
|
|
)
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func animate(duration: TimeInterval, animations: @escaping (() -> Void), completion: ((Bool) -> Void)? = nil) {
|
|
UIView.animate(withDuration: duration, animations: animations, completion: completion)
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func animate(animations: @escaping (() -> Void), completion: ((Bool) -> Void)? = nil) {
|
|
animate(duration: UIViewAnimationDuration, animations: animations, completion: completion)
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func pop() {
|
|
setScale(x: 1.1, y: 1.1)
|
|
spring(duration: 0.2, animations: { [unowned self] () -> Void in
|
|
self.setScale(x: 1, y: 1)
|
|
})
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func popBig() {
|
|
setScale(x: 1.25, y: 1.25)
|
|
spring(duration: 0.2, animations: { [unowned self] () -> Void in
|
|
self.setScale(x: 1, y: 1)
|
|
})
|
|
}
|
|
|
|
//EZSE: Reverse pop, good for button animations
|
|
public func reversePop() {
|
|
setScale(x: 0.9, y: 0.9)
|
|
UIView.animate(withDuration: 0.05, delay: 0, options: .allowUserInteraction, animations: {[weak self] in
|
|
self?.setScale(x: 1, y: 1)
|
|
}, completion: { (_) in })
|
|
}
|
|
}
|
|
|
|
//TODO: add this to readme
|
|
// MARK: Render Extensions
|
|
extension UIView {
|
|
/// EZSwiftExtensions
|
|
public func toImage () -> UIImage {
|
|
UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0.0)
|
|
drawHierarchy(in: bounds, afterScreenUpdates: false)
|
|
let img = UIGraphicsGetImageFromCurrentImageContext()
|
|
UIGraphicsEndImageContext()
|
|
return img!
|
|
}
|
|
}
|
|
|
|
// MARK: Gesture Extensions
|
|
extension UIView {
|
|
/// http://stackoverflow.com/questions/4660371/how-to-add-a-touch-event-to-a-uiview/32182866#32182866
|
|
/// EZSwiftExtensions
|
|
public func addTapGesture(tapNumber: Int = 1, target: AnyObject, action: Selector) {
|
|
let tap = UITapGestureRecognizer(target: target, action: action)
|
|
tap.numberOfTapsRequired = tapNumber
|
|
addGestureRecognizer(tap)
|
|
isUserInteractionEnabled = true
|
|
}
|
|
|
|
/// EZSwiftExtensions - Make sure you use "[weak self] (gesture) in" if you are using the keyword self inside the closure or there might be a memory leak
|
|
public func addTapGesture(tapNumber: Int = 1, action: ((UITapGestureRecognizer) -> Void)?) {
|
|
let tap = BlockTap(tapCount: tapNumber, fingerCount: 1, action: action)
|
|
addGestureRecognizer(tap)
|
|
isUserInteractionEnabled = true
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func addSwipeGesture(direction: UISwipeGestureRecognizerDirection, numberOfTouches: Int = 1, target: AnyObject, action: Selector) {
|
|
let swipe = UISwipeGestureRecognizer(target: target, action: action)
|
|
swipe.direction = direction
|
|
|
|
#if os(iOS)
|
|
|
|
swipe.numberOfTouchesRequired = numberOfTouches
|
|
|
|
#endif
|
|
|
|
addGestureRecognizer(swipe)
|
|
isUserInteractionEnabled = true
|
|
}
|
|
|
|
/// EZSwiftExtensions - Make sure you use "[weak self] (gesture) in" if you are using the keyword self inside the closure or there might be a memory leak
|
|
public func addSwipeGesture(direction: UISwipeGestureRecognizerDirection, numberOfTouches: Int = 1, action: ((UISwipeGestureRecognizer) -> Void)?) {
|
|
let swipe = BlockSwipe(direction: direction, fingerCount: numberOfTouches, action: action)
|
|
addGestureRecognizer(swipe)
|
|
isUserInteractionEnabled = true
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func addPanGesture(target: AnyObject, action: Selector) {
|
|
let pan = UIPanGestureRecognizer(target: target, action: action)
|
|
addGestureRecognizer(pan)
|
|
isUserInteractionEnabled = true
|
|
}
|
|
|
|
/// EZSwiftExtensions - Make sure you use "[weak self] (gesture) in" if you are using the keyword self inside the closure or there might be a memory leak
|
|
public func addPanGesture(action: ((UIPanGestureRecognizer) -> Void)?) {
|
|
let pan = BlockPan(action: action)
|
|
addGestureRecognizer(pan)
|
|
isUserInteractionEnabled = true
|
|
}
|
|
|
|
#if os(iOS)
|
|
|
|
/// EZSwiftExtensions
|
|
public func addPinchGesture(target: AnyObject, action: Selector) {
|
|
let pinch = UIPinchGestureRecognizer(target: target, action: action)
|
|
addGestureRecognizer(pinch)
|
|
isUserInteractionEnabled = true
|
|
}
|
|
|
|
#endif
|
|
|
|
#if os(iOS)
|
|
|
|
/// EZSwiftExtensions - Make sure you use "[weak self] (gesture) in" if you are using the keyword self inside the closure or there might be a memory leak
|
|
public func addPinchGesture(action: ((UIPinchGestureRecognizer) -> Void)?) {
|
|
let pinch = BlockPinch(action: action)
|
|
addGestureRecognizer(pinch)
|
|
isUserInteractionEnabled = true
|
|
}
|
|
|
|
#endif
|
|
|
|
/// EZSwiftExtensions
|
|
public func addLongPressGesture(target: AnyObject, action: Selector) {
|
|
let longPress = UILongPressGestureRecognizer(target: target, action: action)
|
|
addGestureRecognizer(longPress)
|
|
isUserInteractionEnabled = true
|
|
}
|
|
|
|
/// EZSwiftExtensions - Make sure you use "[weak self] (gesture) in" if you are using the keyword self inside the closure or there might be a memory leak
|
|
public func addLongPressGesture(action: ((UILongPressGestureRecognizer) -> Void)?) {
|
|
let longPress = BlockLongPress(action: action)
|
|
addGestureRecognizer(longPress)
|
|
isUserInteractionEnabled = true
|
|
}
|
|
}
|
|
|
|
//TODO: add to readme
|
|
extension UIView {
|
|
/// EZSwiftExtensions [UIRectCorner.TopLeft, UIRectCorner.TopRight]
|
|
public func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
|
|
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
|
|
let mask = CAShapeLayer()
|
|
mask.path = path.cgPath
|
|
self.layer.mask = mask
|
|
}
|
|
|
|
/// EZSwiftExtensions - Mask square/rectangle UIView with a circular/capsule cover, with a border of desired color and width around it
|
|
public func roundView(withBorderColor color: UIColor? = nil, withBorderWidth width: CGFloat? = nil) {
|
|
self.setCornerRadius(radius: min(self.frame.size.height, self.frame.size.width) / 2)
|
|
self.layer.borderWidth = width ?? 0
|
|
self.layer.borderColor = color?.cgColor ?? UIColor.clear.cgColor
|
|
}
|
|
|
|
/// EZSwiftExtensions - Remove all masking around UIView
|
|
public func nakedView() {
|
|
self.layer.mask = nil
|
|
self.layer.borderWidth = 0
|
|
}
|
|
}
|
|
|
|
extension UIView {
|
|
///EZSE: Shakes the view for as many number of times as given in the argument.
|
|
public func shakeViewForTimes(_ times: Int) {
|
|
let anim = CAKeyframeAnimation(keyPath: "transform")
|
|
anim.values = [
|
|
NSValue(caTransform3D: CATransform3DMakeTranslation(-5, 0, 0 )),
|
|
NSValue(caTransform3D: CATransform3DMakeTranslation( 5, 0, 0 ))
|
|
]
|
|
anim.autoreverses = true
|
|
anim.repeatCount = Float(times)
|
|
anim.duration = 7/100
|
|
|
|
self.layer.add(anim, forKey: nil)
|
|
}
|
|
}
|
|
|
|
extension UIView {
|
|
///EZSE: Loops until it finds the top root view. //TODO: Add to readme
|
|
func rootView() -> UIView {
|
|
guard let parentView = superview else {
|
|
return self
|
|
}
|
|
return parentView.rootView()
|
|
}
|
|
}
|
|
|
|
// MARK: Fade Extensions
|
|
|
|
public let UIViewDefaultFadeDuration: TimeInterval = 0.4
|
|
|
|
extension UIView {
|
|
///EZSE: Fade in with duration, delay and completion block.
|
|
public func fadeIn(_ duration: TimeInterval? = UIViewDefaultFadeDuration, delay: TimeInterval? = 0.0, completion: ((Bool) -> Void)? = nil) {
|
|
fadeTo(1.0, duration: duration, delay: delay, completion: completion)
|
|
}
|
|
|
|
/// EZSwiftExtensions
|
|
public func fadeOut(_ duration: TimeInterval? = UIViewDefaultFadeDuration, delay: TimeInterval? = 0.0, completion: ((Bool) -> Void)? = nil) {
|
|
fadeTo(0.0, duration: duration, delay: delay, completion: completion)
|
|
}
|
|
|
|
/// Fade to specific value with duration, delay and completion block.
|
|
public func fadeTo(_ value: CGFloat, duration: TimeInterval? = UIViewDefaultFadeDuration, delay: TimeInterval? = 0.0, completion: ((Bool) -> Void)? = nil) {
|
|
UIView.animate(withDuration: duration ?? UIViewDefaultFadeDuration, delay: delay ?? UIViewDefaultFadeDuration, options: .curveEaseInOut, animations: {
|
|
self.alpha = value
|
|
}, completion: completion)
|
|
}
|
|
}
|
|
|
|
#endif
|