202 lines
7.5 KiB
Swift
202 lines
7.5 KiB
Swift
//
|
|
// UIView.swift
|
|
// List
|
|
//
|
|
// Created by Igor Danich on 30.06.2020.
|
|
// Copyright © 2020 Igor Danich. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
|
|
// MARK: - REFACTOR
|
|
|
|
extension UIView {
|
|
var frameOrigin: CGPoint {
|
|
get { frame.origin }
|
|
set { frame = CGRect(origin: newValue, size: frameSize) }
|
|
}
|
|
var frameX: CGFloat {
|
|
get { frameOrigin.x }
|
|
set { frameOrigin = CGPoint(x: newValue, y: frameY) }
|
|
}
|
|
var frameY: CGFloat {
|
|
get { frameOrigin.y }
|
|
set { frameOrigin = CGPoint(x: frameX, y: newValue) }
|
|
}
|
|
var frameSize: CGSize {
|
|
get { frame.size }
|
|
set { frame = CGRect(origin: frameOrigin, size: newValue) }
|
|
}
|
|
var frameWidth: CGFloat {
|
|
get { frameSize.width }
|
|
set { frameSize = CGSize(width: newValue, height: frameHeight)}
|
|
}
|
|
var frameHeight: CGFloat {
|
|
get { frameSize.height }
|
|
set { frameSize = CGSize(width: frameWidth, height: newValue) }
|
|
}
|
|
var centerX: CGFloat {
|
|
get { center.x }
|
|
set { center = .init(x: newValue, y: center.y)}
|
|
}
|
|
var centerY: CGFloat {
|
|
get { center.y }
|
|
set { center = .init(x: center.x, y: newValue)}
|
|
}
|
|
|
|
func drawGradient(startColor: UIColor, endColor: UIColor) {
|
|
let gradient = CAGradientLayer()
|
|
gradient.frame = bounds
|
|
gradient.colors = [startColor.cgColor, endColor.cgColor]
|
|
gradient.startPoint = CGPoint(x: 0.0, y: 0.7)
|
|
gradient.endPoint = CGPoint(x: 1.0, y: 0.7)
|
|
layer.insertSublayer(gradient, at: 0)
|
|
}
|
|
func drawDotted(color: UIColor) {
|
|
let border = CAShapeLayer()
|
|
border.strokeColor = color.cgColor
|
|
border.lineDashPattern = [10, 2]
|
|
border.frame = bounds
|
|
border.fillColor = nil
|
|
border.masksToBounds = true
|
|
border.lineJoin = .round
|
|
border.path = UIBezierPath(roundedRect: bounds, cornerRadius: 20).cgPath
|
|
layer.addSublayer(border)
|
|
}
|
|
func addShadow(color: UIColor, opacity: CGFloat = 1, radius: CGFloat, offset: CGSize = .zero, cornerRadius: CGFloat, index: Int? = nil) {
|
|
addShadow(color: color, radius: radius, offset: offset, path: UIBezierPath(roundedRect: bounds, cornerRadius: cornerRadius), index: index)
|
|
}
|
|
func addShadow(color: UIColor, opacity: CGFloat = 1, radius: CGFloat, offset: CGSize = .zero, path: UIBezierPath? = nil, index: Int? = nil) {
|
|
let layer = CALayer()
|
|
layer.frame = bounds
|
|
layer.shadowColor = color.cgColor
|
|
layer.shadowRadius = radius
|
|
layer.shadowOffset = offset
|
|
layer.shadowOpacity = Float(opacity)
|
|
if let path = path { layer.shadowPath = path.cgPath }
|
|
if let index = index {
|
|
self.layer.insertSublayer(layer, at: UInt32(index))
|
|
} else {
|
|
self.layer.addSublayer(layer)
|
|
}
|
|
}
|
|
}
|
|
|
|
extension UINib {
|
|
func instantiate() -> Any? { self.instantiate(withOwner: nil, options: nil).first }
|
|
}
|
|
|
|
extension UIView {
|
|
static var nib: UINib { UINib(nibName: String(describing: self), bundle: nil) }
|
|
static func instantiate(autolayout: Bool = true) -> Self {
|
|
func instantiateUsingNib<T: UIView>(autolayout: Bool) -> T {
|
|
// swiftlint:disable force_cast
|
|
let view = self.nib.instantiate() as! T
|
|
view.translatesAutoresizingMaskIntoConstraints = !autolayout
|
|
return view
|
|
}
|
|
return instantiateUsingNib(autolayout: autolayout)
|
|
}
|
|
func loadViewFromNib(nibName: String) {
|
|
let bundle = Bundle(for: type(of: self))
|
|
let nib = UINib(nibName: nibName, bundle: bundle)
|
|
guard let view = nib.instantiate(withOwner: self, options: nil).first as? UIView else { return }
|
|
view.frame = bounds
|
|
view.isUserInteractionEnabled = false
|
|
addSubview(view)
|
|
}
|
|
}
|
|
|
|
extension UIView {
|
|
func addHeightWidthConstraints(height: CGFloat, width: CGFloat) { addHeightConstraint(height: height);addWidthConstraint(width: width) }
|
|
func addHeightConstraint(height: CGFloat) { heightAnchor.constraint(equalToConstant: height).isActive = true }
|
|
func addWidthConstraint(width: CGFloat) { widthAnchor.constraint(equalToConstant: width).isActive = true }
|
|
}
|
|
|
|
extension UIView {
|
|
convenience init(height: CGFloat, color: UIColor? = .clear) {
|
|
self.init(frame: CGRect(x: 0, y: 0, width: 0, height: height))
|
|
self.addHeightConstraint(height: height)
|
|
if let color = color { self.backgroundColor = color }
|
|
}
|
|
convenience init(width: CGFloat, height: CGFloat, color: UIColor? = .clear) {
|
|
self.init(frame: CGRect(x: 0, y: 0, width: width, height: height))
|
|
self.addHeightWidthConstraints(height: height, width: width)
|
|
if let color = color { self.backgroundColor = color }
|
|
}
|
|
convenience init(width: CGFloat, color: UIColor? = .clear) {
|
|
self.init(frame: CGRect(x: 0, y: 0, width: width, height: 0))
|
|
self.addWidthConstraint(width: width)
|
|
if let color = color { self.backgroundColor = color }
|
|
}
|
|
}
|
|
|
|
extension UIView {
|
|
static func view<T:UIView>(frame: CGRect = .zero, _ configure: (T) -> Void) -> T { T.object({ $0.frame = frame;configure($0) }) }
|
|
func animateIfNeeded(duration: Animation = .medium, execute: (() -> Void)? = nil) {
|
|
condition(
|
|
duration == .none,
|
|
true: { execute?();self.layoutIfNeeded();return nil },
|
|
false: { UIView.animate(withDuration: duration) { execute?();self.layoutIfNeeded() } }
|
|
)
|
|
}
|
|
}
|
|
|
|
extension UIView {
|
|
static func view(bacgroundColor: UIColor? = .clear, width: CGFloat? = nil, height: CGFloat? = nil) -> UIView {
|
|
let view = UIView()
|
|
view.backgroundColor = bacgroundColor
|
|
if let width = width {
|
|
view.widthAnchor.constraint(equalToConstant: width).isActive = true
|
|
}
|
|
if let height = height {
|
|
view.heightAnchor.constraint(equalToConstant: height).isActive = true
|
|
}
|
|
return view
|
|
}
|
|
}
|
|
|
|
extension UIView {
|
|
func drawVerticalGradient(startColor: UIColor, endColor: UIColor) {
|
|
let gradient = CAGradientLayer()
|
|
gradient.frame = CGRect(x: CGFloat(0),
|
|
y: CGFloat(0),
|
|
width: frame.size.width,
|
|
height: frame.size.height)
|
|
gradient.colors = [startColor.cgColor, endColor.cgColor]
|
|
gradient.startPoint = CGPoint(x: 0.5, y: 0.0)
|
|
gradient.endPoint = CGPoint(x: 0.5, y: 1.0)
|
|
layer.insertSublayer(gradient, at: 0)
|
|
}
|
|
}
|
|
|
|
final class BindableGestureRecognizer: UITapGestureRecognizer {
|
|
private var action: () -> Void
|
|
|
|
init(action: @escaping () -> Void) {
|
|
self.action = action
|
|
super.init(target: nil, action: nil)
|
|
self.addTarget(self, action: #selector(execute))
|
|
}
|
|
|
|
@objc private func execute() {
|
|
action()
|
|
}
|
|
}
|
|
|
|
public extension UIView {
|
|
/// A discrete gesture recognizer that interprets single or multiple taps.
|
|
/// - Parameters:
|
|
/// - tapNumber: The number of taps necessary for gesture recognition.
|
|
/// - closure: A selector that identifies the method implemented by the target to handle the gesture recognized by the receiver. The action selector must conform to the signature described in the class overview. NULL is not a valid value.
|
|
func addTapGesture(tapNumber: Int = 1, _ closure: (() -> Void)?) {
|
|
guard let closure = closure else { return }
|
|
|
|
let tap = BindableGestureRecognizer(action: closure)
|
|
tap.numberOfTapsRequired = tapNumber
|
|
addGestureRecognizer(tap)
|
|
|
|
isUserInteractionEnabled = true
|
|
}
|
|
}
|