Skip to content

Instantly share code, notes, and snippets.

@mukhortov
Created February 28, 2018 08:11
Show Gist options
  • Save mukhortov/6a09562b4e07efbdcd293b12616c6bf4 to your computer and use it in GitHub Desktop.
Save mukhortov/6a09562b4e07efbdcd293b12616c6bf4 to your computer and use it in GitHub Desktop.
Visibility Toggler UIView Extension
//
// VisibilityToggler+UIView.swift
//
private var associatedPropertyHeight: CGFloat = 0
private var associatedPropertyWidth: CGFloat = 0
extension UIView {
fileprivate var visibilityConstraintIdentifier: String { return "UIVisibilityGenerated" }
fileprivate var height: CGFloat? {
get {
return objc_getAssociatedObject(self, &associatedPropertyHeight) as? CGFloat
}
set(newValue) {
objc_setAssociatedObject(self, &associatedPropertyHeight, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
fileprivate var width: CGFloat? {
get {
return objc_getAssociatedObject(self, &associatedPropertyWidth) as? CGFloat
}
set(newValue) {
objc_setAssociatedObject(self, &associatedPropertyWidth, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
func updateConstrainedHeight(_ height: CGFloat) {
if let constraint = getConstraintBy(type: .height) {
constraint.constant = height
}
self.height = height
}
func updateConstrainedWidth(_ width: CGFloat) {
if let constraint = getConstraintBy(type: .width) {
constraint.constant = width
}
self.width = width
}
func zeroHeight(animated: Bool = false) {
if animated {
superview?.layoutIfNeeded()
UIView.animate(withDuration: 0.3, animations: {
self.zeroHeightContraint()
})
} else {
zeroHeightContraint()
}
}
private func zeroHeightContraint() {
clipsToBounds = true
if let constraint = getConstraintBy(type: .height) {
if constraint.constant > 0 {
self.height = constraint.constant
}
constraint.constant = 0
superview?.layoutIfNeeded()
}
}
func zeroWidth() {
clipsToBounds = true
if let constraint = getConstraintBy(type: .width) {
if constraint.constant > 0 {
self.width = constraint.constant
}
constraint.constant = 0
superview?.layoutIfNeeded()
}
}
func restoreHeight(animated: Bool = false) {
if animated {
superview?.layoutIfNeeded()
UIView.animate(withDuration: 0.3, animations: {
self.restoreHeightConstraint()
})
} else {
restoreHeightConstraint()
}
}
private func restoreHeightConstraint() {
if let constraint = getConstraintBy(type: .height) {
if constraint.constant == 0 {
if self.height != nil {
constraint.constant = self.height!
} else {
constraint.constant = self.frame.height
}
if constraint.identifier == visibilityConstraintIdentifier {
removeConstraint(constraint)
}
superview?.layoutIfNeeded()
}
}
}
func restoreWidth() {
if let constraint = getConstraintBy(type: .width) {
if constraint.constant == 0 {
if self.width != nil {
constraint.constant = self.width!
} else {
constraint.constant = self.frame.width
}
if constraint.identifier == visibilityConstraintIdentifier {
removeConstraint(constraint)
}
superview?.layoutIfNeeded()
}
}
}
func getConstant(type: NSLayoutAttribute) -> CGFloat? {
guard let constraint = getConstraintBy(type: type) else { return nil }
return constraint.constant
}
func isVisible() -> Bool {
if let heightConstraint = getConstraintBy(type: .height, createNewIfNotFound: false) {
return heightConstraint.constant != 0 && isHidden == false
} else if let widthConstraint = getConstraintBy(type: .width, createNewIfNotFound: false) {
return widthConstraint.constant != 0 && isHidden == false
}
return isHidden == false
}
fileprivate func getConstraintBy(type: NSLayoutAttribute, createNewIfNotFound: Bool = true) -> NSLayoutConstraint? {
var returnConstraint: NSLayoutConstraint? = nil
for constraint in self.constraints {
if constraint.firstAttribute == type && type(of: constraint) == NSLayoutConstraint.self {
if returnConstraint == nil {
returnConstraint = constraint
} else {
AppLogWarning("Operating on view with multiple \(type.rawValue) constraints: \(constraint)")
}
}
}
if returnConstraint == nil && createNewIfNotFound {
let newConstraint = NSLayoutConstraint(item: self, attribute: type, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 0)
newConstraint.identifier = visibilityConstraintIdentifier
addConstraint(newConstraint)
returnConstraint = newConstraint
}
return returnConstraint
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment