Last active
October 10, 2020 15:26
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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