Skip to content

Instantly share code, notes, and snippets.

@mathiarasan24
Last active October 10, 2020 15:26
Show Gist options
  • Select an option

  • Save mathiarasan24/f9b5471918fd951b7ed37d4e57a5c87e to your computer and use it in GitHub Desktop.

Select an option

Save mathiarasan24/f9b5471918fd951b7ed37d4e57a5c87e to your computer and use it in GitHub Desktop.
Align current view to super view with a single method!. Depends/Not depends with any of these side (Top, bottom, leading and trailing) or greater than equal or lesser than equal to super view with custom padding.
extension UIView {
public typealias kCompletionHandler = (Bool) -> Void
enum ConstraintType {
case none
case equalTo(CGFloat)
case greaterThan(CGFloat)
case lesserThan(CGFloat)
}
enum MAiAnimationType {
case fadeIn(CGFloat) // alpha to Value
case fadeOut(CGFloat) // alpha to Value : View won't remove or hide
case layout
case custom
}
class func viewInit(bgColor: UIColor = .white) -> UIView {
let returnView = UIView()
returnView.translatesAutoresizingMaskIntoConstraints = false
returnView.backgroundColor = bgColor
return returnView
}
func alignToSuperView(top: ConstraintType = .equalTo(0),
leading: ConstraintType = .equalTo(0),
bottom: ConstraintType = .equalTo(0),
trailing: ConstraintType = .equalTo(0),
height: ConstraintType = .equalTo(0),
width: ConstraintType = .equalTo(0)) {
enum AnchorType {
case top(ConstraintType)
case leading(ConstraintType)
case bottom(ConstraintType)
case trailing(ConstraintType)
case heihgt(ConstraintType)
case width(ConstraintType)
}
func stringValue(for type: AnchorType) -> String {
func valueFor(type constraintType: ConstraintType) -> String? {
switch constraintType {
case .none:
return nil
case .equalTo(let value):
return "(\(value))"
case .greaterThan(let value):
return "(>=\(value))"
case .lesserThan(let value):
return "(<=\(value))"
}
}
switch type {
case .top(let constraintType):
guard let haveString = valueFor(type: constraintType) else { return "" }
return "V:|-\(haveString)-"
case .leading(let constraintType):
guard let haveString = valueFor(type: constraintType) else { return "" }
return "H:|-\(haveString)-"
case .bottom(let constraintType),
.trailing(let constraintType):
guard let haveString = valueFor(type: constraintType) else { return "" }
return "-\(haveString)-|"
case .heihgt(let constraintType),
.width(let constraintType):
switch constraintType {
case .none:
return ""
case .equalTo(let value):
guard value != 0 else { return "" }
fallthrough
case .greaterThan(_),
.lesserThan(_):
guard let haveString = valueFor(type: constraintType) else { return "" }
return haveString
}
}
}
let metricDict: [String: CGFloat]? = nil
var constraintArray: [NSLayoutConstraint] = []
let viewDict: [String: UIView] = ["view": self]
constraintArray.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: "\(stringValue(for: .top(top)))[view\(stringValue(for: .heihgt(height)))]\(stringValue(for: .bottom(bottom)))", options: [], metrics: metricDict, views: viewDict))
constraintArray.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: "\(stringValue(for: .leading(leading)))[view\(stringValue(for: .width(width)))]\(stringValue(for: .trailing(trailing)))", options: [], metrics: metricDict, views: viewDict))
NSLayoutConstraint.activate(constraintArray)
}
func animate(type: MAiAnimationType,
with duration: TimeInterval = 0.3,
delay: TimeInterval = 0.0,
options: UIView.AnimationOptions = [],
animations: (() -> Void)? = nil,
completion: kCompletionHandler? = nil) {
func startAnimate() {
UIView.animate(withDuration: duration,
delay: 0,
options: options,
animations: { [weak self] in
switch type {
case .fadeIn(let alphaValue),
.fadeOut(let alphaValue):
self?.alpha = alphaValue
case .layout:
self?.layoutIfNeeded()
case .custom:
animations?()
}
animations?()
})
}
func completionAtEnd() {
// UIView animate doesn't work as expected with completion handuler so creating static dispatch queue with animation duration
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + duration, execute: { () -> Void in
completion?(true)
})
}
// UIView animate doesn't work as expected with delay so creating static dispatch queue delay only if delay greater than 0
if delay > 0 {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delay, execute: { () -> Void in
startAnimate()
completionAtEnd()
})
} else {
startAnimate()
completionAtEnd()
}
}
func shadow(radius: CGFloat = 5,
opacity: Float = 0.5,
offset: CGSize = CGSize(width:0, height:3),
color: UIColor = .black) {
layer.shadowRadius = radius
layer.shadowOpacity = opacity
layer.shadowOffset = offset
layer.masksToBounds = false
layer.shadowColor = color.cgColor
}
func radius(value: CGFloat) {
layer.cornerRadius = value
layer.masksToBounds = true
}
}
/// Code usage
let yourView = UIView()
yourView.translatesAutoresizingMaskIntoConstraints = false
superView.addSubview(yourView)
/// Align all side equalt to superview with 0 padding space
/// So, current height and widht equal to superview height and width
yourView.alignToSuperView()
/// Align all side equalt to superview with 10 padding space
/// So, current height and widht lesser than 10 from superview height and width
yourView.alignToSuperView(to: .equalTo(10))
/// Align all side equalt to superview with -10 padding space
/// Height is greater than equal to -10
/// Width is lesser than equal to 10
yourView.alignToSuperView(to: .equalTo(-10),
height: .greaterThan(10),
width: .lesserThan(10))
/// Current view doesn't have origin Y axis (Top) and bottom based on superview
/// Align herizontal (Leading and Trailing) side greater than equalt to superview with 10 padding space
/// Height is greater than equal to 50
/// Width based on horizontal padding
yourView.alignToSuperView(vertical: .none,
horizontal: .greaterThan(10),
height: .equalTo(50))
/// Current view doesn't have origin Y axis (Top) and bottom based on superview
/// Align leading side equalt to superview with 100 padding space
/// Align bottom side lesser than equalt to superview with 10 padding space
/// Align trailing side greater than equalt to superview with -10 padding space
/// Height based on top and bottom padding
/// Width is based on leading and trailing
yourView.alignToSuperView(top: .none,
leading: .equalTo(100),
bottom: .lesserThan(10),
trailing: .greaterThan(-10),
width: .none)
/// Animate based on layout it'll helpfull for constraint/frame changes animation
yourView.animate(type: .layout, with: animationDuration, completion: completion)
/// Alpha value change previous value into 1.0 (Based on input value)
/// If animation should start with a delay we can it here
yourView.animate(type: .fadeIn(1.0), with: animationDuration, delay: animationDuration)
yourView.animate(type: .custom, animations: { _ in
// Your custom code to animate
}, completion: { [weak self] (isSuccess) in
// Your custom code after animation success
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment