diff --git a/README.md b/README.md index 49da837..6fb5b57 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ pod 'SurfUtils/$UTIL_NAME$', :git => "https://github.com/surfstudio/iOS-Utils.gi - [SkeletonView](#skeletonview) - cпециальная кастомная View для создания skeleton loader'ов - [OTPField](#otpfield) - кастомный филд для работы с One Time Password - [XibView](#xibview) - для работы UIView + xib +- [UIImageExtensions](#uiimageextensions) - набор часто используемых extensions для UIImage +- [CommonButton](#commonbutton) - Базовый класс для кнопки ## Утилиты @@ -311,6 +313,37 @@ required init?(coder aDecoder: NSCoder) { } ``` +### UIImageExtensions + +Набор часто используемых extensions для работы с UIImage + +* Инициализатор позволяющий создать картинку с заданным цветом и размером + + ```swift + convenience init?(color: UIColor?, size: CGSize = CGSize(width: 1, height: 1)) + ``` + +* Метод **mask** – позволяет сделать картинку с заданным цветом или изменить параметры альфы у цвета картинки + + ```swift + func mask(with color: UIColor) -> UIImage + func mask(with alpha: CGFloat) -> UIImage + ``` + +### CommonButton + +Базовый класс для UIButton. Упрощает работу с доступными у класса UIButton параметрами. + +Базовые возможности: + +* Устанавливать бекграунд у кнопки для массива состояний +* Устанавливать цвет тайтла кнопки для массива состояний +* Устанавливать значения для border у кнопки +* Изменять cornerRadius +* Увеличивать область нажатия у кнопки +* Устанавливать значение тайтла для всех состояний сразу +* Устанавливать значение картинки кнопки для всех состояний сразу + ## Версионирование В качестве принципа версионирования используется [Семантическое версионирования (Semantic Versioning)](https://semver.org/). diff --git a/SurfUtils.podspec b/SurfUtils.podspec index ecbaba7..0d616b8 100644 --- a/SurfUtils.podspec +++ b/SurfUtils.podspec @@ -88,4 +88,14 @@ Pod::Spec.new do |s| sp.framework = 'UIKit' end + s.subspec 'UIImageExtensions' do |sp| + sp.source_files = 'Utils/Utils/UIImage/UIImageExtensions.swift' + sp.framework = 'UIKit' + end + + s.subspec 'CommonButton' do |sp| + sp.source_files = 'Utils/Utils/CommonButton/CommonButton.swift', 'Utils/Utils/UIImage/UIImageExtensions.swift' + sp.framework = 'UIKit' + end + end diff --git a/Utils/Utils.xcodeproj/project.pbxproj b/Utils/Utils.xcodeproj/project.pbxproj index 679f240..a70b507 100644 --- a/Utils/Utils.xcodeproj/project.pbxproj +++ b/Utils/Utils.xcodeproj/project.pbxproj @@ -11,6 +11,8 @@ 4F3ED9E9211C27CF0030DD45 /* Utils.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4F3ED9DF211C27CF0030DD45 /* Utils.framework */; }; 4F3ED9F0211C27CF0030DD45 /* Utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 4F3ED9E2211C27CF0030DD45 /* Utils.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4F3ED9FC211C27FD0030DD45 /* String+Attributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3ED9FB211C27FD0030DD45 /* String+Attributes.swift */; }; + 5709EC5D236F4C6500EEBD93 /* CommonButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5709EC5C236F4C6500EEBD93 /* CommonButton.swift */; }; + 5709EC6A236F562400EEBD93 /* UIImageExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5709EC69236F562400EEBD93 /* UIImageExtensions.swift */; }; 80437D26214045EF0095A8D0 /* BrightSide.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80437D25214045EF0095A8D0 /* BrightSide.swift */; }; 8953A46D23560A2F007AD110 /* OTPField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8953A46C23560A2F007AD110 /* OTPField.swift */; }; 8953A46F23560A4C007AD110 /* OTPField.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8953A46E23560A4C007AD110 /* OTPField.xib */; }; @@ -59,6 +61,8 @@ 4F3ED9E8211C27CF0030DD45 /* UtilsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UtilsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 4F3ED9EF211C27CF0030DD45 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 4F3ED9FB211C27FD0030DD45 /* String+Attributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Attributes.swift"; sourceTree = ""; }; + 5709EC5C236F4C6500EEBD93 /* CommonButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonButton.swift; sourceTree = ""; }; + 5709EC69236F562400EEBD93 /* UIImageExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageExtensions.swift; sourceTree = ""; }; 80437D25214045EF0095A8D0 /* BrightSide.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrightSide.swift; sourceTree = ""; }; 8953A46C23560A2F007AD110 /* OTPField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OTPField.swift; sourceTree = ""; }; 8953A46E23560A4C007AD110 /* OTPField.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = OTPField.xib; sourceTree = ""; }; @@ -137,6 +141,7 @@ 4F3ED9E1211C27CF0030DD45 /* Utils */ = { isa = PBXGroup; children = ( + 5709EC5B236F4C2200EEBD93 /* CommonButton */, 18F2361221D214CC00169AC9 /* Dictionary */, 902C67EA21E4D1EF007B13CC /* ItemsScrollManager */, 80437D24214045B30095A8D0 /* BrightSide */, @@ -145,6 +150,7 @@ 907F0FE421DCD375001CCB07 /* SettingsRouter */, A439074C21F5C5510034C455 /* SkeletonView */, 4F3ED9FA211C27E80030DD45 /* String */, + 5709EC68236F55AA00EEBD93 /* UIImage */, 907F0FE121DCD1DB001CCB07 /* UINavigationController */, 902CA33F21E732F700396923 /* UIView */, E9B06306214691F30080C391 /* VibrationFeedbackManager */, @@ -175,6 +181,22 @@ path = String; sourceTree = ""; }; + 5709EC5B236F4C2200EEBD93 /* CommonButton */ = { + isa = PBXGroup; + children = ( + 5709EC5C236F4C6500EEBD93 /* CommonButton.swift */, + ); + path = CommonButton; + sourceTree = ""; + }; + 5709EC68236F55AA00EEBD93 /* UIImage */ = { + isa = PBXGroup; + children = ( + 5709EC69236F562400EEBD93 /* UIImageExtensions.swift */, + ); + path = UIImage; + sourceTree = ""; + }; 80437D24214045B30095A8D0 /* BrightSide */ = { isa = PBXGroup; children = ( @@ -424,10 +446,12 @@ A439074E21F5C5880034C455 /* SkeletonView.swift in Sources */, 80437D26214045EF0095A8D0 /* BrightSide.swift in Sources */, 898845202360482D004940DC /* UIView+XibSetup.swift in Sources */, + 5709EC5D236F4C6500EEBD93 /* CommonButton.swift in Sources */, 9087BC5221EF3BE700FCE1E1 /* CommonKeyboardPresentable.swift in Sources */, 9087BC5021EF3BD400FCE1E1 /* KeyboardObservable.swift in Sources */, E9B0630E214693160080C391 /* UIDevice+hasHapticFeedback.swift in Sources */, 90718AF121EA370000C81002 /* KeyboardNotificationsObserver.swift in Sources */, + 5709EC6A236F562400EEBD93 /* UIImageExtensions.swift in Sources */, 8953A46D23560A2F007AD110 /* OTPField.swift in Sources */, 4F3ED9FC211C27FD0030DD45 /* String+Attributes.swift in Sources */, 902CA34121E7331E00396923 /* UIView+BlurBuilder.swift in Sources */, diff --git a/Utils/Utils/CommonButton/CommonButton.swift b/Utils/Utils/CommonButton/CommonButton.swift new file mode 100644 index 0000000..12b7ae1 --- /dev/null +++ b/Utils/Utils/CommonButton/CommonButton.swift @@ -0,0 +1,106 @@ +// +// CommonButton.swift +// Utils +// +// Created by Александр Чаусов on 28/01/2019. +// Copyright © 2019 Surf. All rights reserved. +// + +import UIKit + +open class CommonButton: UIButton { + + // MARK: - Public Properties + + public var borderColor: UIColor? { + didSet { + layer.borderColor = borderColor?.cgColor + } + } + + public var borderWidth: CGFloat = 0 { + didSet { + layer.borderWidth = borderWidth + } + } + + public var cornerRadius: CGFloat { + get { + return layer.cornerRadius + } + set { + layer.cornerRadius = newValue + layer.masksToBounds = newValue > 0 + } + } + + /// Increase touch area + public var addedTouchArea: CGFloat = 0.0 + + // MARK: - Initialization + + override public init(frame: CGRect) { + super.init(frame: frame) + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + override open func awakeFromNib() { + super.awakeFromNib() + } + + // MARK: - UIButton + + override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + let newBound = CGRect( + x: bounds.origin.x - addedTouchArea, + y: bounds.origin.y - addedTouchArea, + width: bounds.width + 2 * addedTouchArea, + height: bounds.height + 2 * addedTouchArea + ) + return newBound.contains(point) + } + + // MARK: - Public Methods + + /// Method set title for all states + public func setTitleForAllState(_ title: String?) { + setTitle(title, for: .normal) + setTitle(title, for: .disabled) + setTitle(title, for: .highlighted) + setTitle(title, for: .selected) + } + + /// Method set image for all states + /// If use alpha image with alpha mask will set for disabled, highlighted, selected states + /// - Parameters: + /// - image: Optional value for set button image + /// - alpha: Optional value for disabled, highlighted, selected states + public func setImageForAllState(_ image: UIImage?, alpha: CGFloat? = nil) { + let highlightedImage = alpha != nil + ? image?.mask(with: alpha ?? 0) + : image + setImage(image, for: .normal) + setImage(highlightedImage, for: .disabled) + setImage(highlightedImage, for: .highlighted) + setImage(highlightedImage, for: .selected) + } + + /// Method will set background color for control state + public func set(backgroundColor: UIColor, for state: UIControl.State) { + setBackgroundImage(UIImage(color: backgroundColor), for: state) + } + + /// Method will set background color for all choosed control states + public func set(backgroundColor: UIColor, for states: [UIControl.State]) { + states.forEach { setBackgroundImage(UIImage(color: backgroundColor), for:$0) } + } + + /// Method will set title color for all choosed control states + public func set(titleColor: UIColor, for states: [UIControl.State]) { + states.forEach { setTitleColor(titleColor, for: $0) } + } + +} diff --git a/Utils/Utils/UIImage/UIImageExtensions.swift b/Utils/Utils/UIImage/UIImageExtensions.swift new file mode 100644 index 0000000..52ca823 --- /dev/null +++ b/Utils/Utils/UIImage/UIImageExtensions.swift @@ -0,0 +1,68 @@ +// +// UIImageExtensions.swift +// Utils +// +// Created by Vladislav Krupenko on 03/11/2019. +// Copyright © 2019 Surf. All rights reserved. +// + +import UIKit + +public extension UIImage { + + /// Init method for creating UIImage of a given color + /// - Parameters: + /// - color: Optional value, by default clear color + /// - size: Optional value, by default size 1*1 + convenience init?(color: UIColor?, size: CGSize = CGSize(width: 1, height: 1)) { + let color = color ?? UIColor.clear + let rect = CGRect(origin: .zero, size: size) + UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0) + color.setFill() + UIRectFill(rect) + let image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + + guard let cgImage = image?.cgImage else { + return nil + } + self.init(cgImage: cgImage) + } + + /// Method returns UIImage with given tint color + func mask(with color: UIColor) -> UIImage { + UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale) + defer { UIGraphicsEndImageContext() } + + guard let context = UIGraphicsGetCurrentContext() else { + return self + } + context.translateBy(x: 0, y: self.size.height) + context.scaleBy(x: 1.0, y: -1.0) + context.setBlendMode(.normal) + + let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height) + guard let mask = self.cgImage else { + return self + } + context.clip(to: rect, mask: mask) + + color.setFill() + context.fill(rect) + + guard let newImage = UIGraphicsGetImageFromCurrentImageContext() else { + return self + } + return newImage + } + + /// Method return UIImage with given alpha + func mask(with alpha: CGFloat) -> UIImage { + UIGraphicsBeginImageContextWithOptions(size, false, scale) + draw(at: .zero, blendMode: .normal, alpha: alpha) + let newImage = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + return newImage ?? self + } + +}