From cbfee175d0a36eeef889e5aed5a82c0fb2877347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Spencer=20M=C3=BCller=20Diniz?= Date: Wed, 2 Jan 2019 16:23:13 -0200 Subject: [PATCH 01/11] Make title and error labels independent. Allow for error label to be displayed below the text field. --- Sources/SkyFloatingLabelTextField.swift | 164 ++++++++++++++++++++++-- 1 file changed, 152 insertions(+), 12 deletions(-) diff --git a/Sources/SkyFloatingLabelTextField.swift b/Sources/SkyFloatingLabelTextField.swift index 3bb382c..296585f 100644 --- a/Sources/SkyFloatingLabelTextField.swift +++ b/Sources/SkyFloatingLabelTextField.swift @@ -11,6 +11,11 @@ import UIKit +public enum ErrorLabelPlacement { + case defaultPlacement + case bottomPlacement +} + /** A beautiful and flexible textfield implementation with support for title label, error message and placeholder. */ @@ -72,6 +77,8 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty updatePlaceholder() } } + + open var errorMessagePlacement: ErrorLabelPlacement = .defaultPlacement fileprivate func updatePlaceholder() { guard let placeholder = placeholder, let font = placeholderFont ?? font else { @@ -196,6 +203,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty /// The internal `UILabel` that displays the selected, deselected title or error message based on the current state. open var titleLabel: UILabel! + open var errorLabel: UILabel! // MARK: Properties @@ -329,6 +337,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty borderStyle = .none createTitleLabel() createLineView() + createErrorLabel() updateColors() addEditingChangedObserver() updateTextAligment() @@ -359,6 +368,17 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty self.titleLabel = titleLabel } + fileprivate func createErrorLabel() { + let errorLabel = UILabel() + errorLabel.autoresizingMask = [.flexibleWidth, .flexibleHeight] + errorLabel.font = titleFont + errorLabel.alpha = 0.0 + errorLabel.textColor = errorColor + + addSubview(errorLabel) + self.errorLabel = errorLabel + } + fileprivate func createLineView() { if lineView == nil { @@ -457,8 +477,10 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty if !isEnabled { titleLabel.textColor = disabledColor - } else if hasErrorMessage { - titleLabel.textColor = titleErrorColor ?? errorColor + } else if hasErrorMessage && errorMessagePlacement == .defaultPlacement { + if errorMessagePlacement == .defaultPlacement { + titleLabel.textColor = titleErrorColor ?? errorColor + } } else { if editingOrSelected || isHighlighted { titleLabel.textColor = selectedTitleColor @@ -486,9 +508,27 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty } var titleText: String? - if hasErrorMessage { - titleText = titleFormatter(errorMessage!) - } else { + var errorText: String? + + if errorMessagePlacement == .defaultPlacement { + if hasErrorMessage { + titleText = titleFormatter(errorMessage!) + } else { + if editingOrSelected { + titleText = selectedTitleOrTitlePlaceholder() + if titleText == nil { + titleText = titleOrPlaceholder() + } + } else { + titleText = titleOrPlaceholder() + } + } + } + else { + if hasErrorMessage { + errorText = titleFormatter(errorMessage!) + } + if editingOrSelected { titleText = selectedTitleOrTitlePlaceholder() if titleText == nil { @@ -498,10 +538,15 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty titleText = titleOrPlaceholder() } } + titleLabel.text = titleText titleLabel.font = titleFont + errorLabel.text = errorText + errorLabel.font = titleFont + updateTitleVisibility(animated) + updateErrorVisibility(animated) } fileprivate var _titleVisible: Bool = false @@ -527,7 +572,16 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty - returns: True if the title is displayed on the control, false otherwise. */ open func isTitleVisible() -> Bool { - return hasText || hasErrorMessage || _titleVisible + if errorMessagePlacement == .defaultPlacement { + return hasText || hasErrorMessage || _titleVisible + } + else { + return hasText || _titleVisible + } + } + + open func isErrorVisible() -> Bool { + return hasErrorMessage } fileprivate func updateTitleVisibility(_ animated: Bool = false, completion: ((_ completed: Bool) -> Void)? = nil) { @@ -553,6 +607,29 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty } } + fileprivate func updateErrorVisibility(_ animated: Bool = false, completion: ((_ completed: Bool) -> Void)? = nil) { + let alpha: CGFloat = isErrorVisible() ? 1.0 : 0.0 + let frame: CGRect = errorLabelRectForBounds(bounds, editing: isErrorVisible()) + let updateBlock = { () -> Void in + self.errorLabel.alpha = alpha + self.errorLabel.frame = frame + } + if animated { + #if swift(>=4.2) + let animationOptions: UIView.AnimationOptions = .curveEaseOut + #else + let animationOptions: UIViewAnimationOptions = .curveEaseOut + #endif + let duration = isErrorVisible() ? titleFadeInDuration : titleFadeOutDuration + UIView.animate(withDuration: duration, delay: 0, options: animationOptions, animations: { () -> Void in + updateBlock() + }, completion: completion) + } else { + updateBlock() + completion?(true) + } + } + // MARK: - UITextField text/placeholder positioning overrides /** @@ -563,12 +640,18 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty override open func textRect(forBounds bounds: CGRect) -> CGRect { let superRect = super.textRect(forBounds: bounds) let titleHeight = self.titleHeight() - + + var height = superRect.size.height - titleHeight - selectedLineHeight + + if errorMessagePlacement == .bottomPlacement { + height = height - errorHeight() + } + let rect = CGRect( x: superRect.origin.x, y: titleHeight, width: superRect.size.width, - height: superRect.size.height - titleHeight - selectedLineHeight + height: height ) return rect } @@ -582,11 +665,17 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty let superRect = super.editingRect(forBounds: bounds) let titleHeight = self.titleHeight() + var height = superRect.size.height - titleHeight - selectedLineHeight + + if errorMessagePlacement == .bottomPlacement { + height = height - errorHeight() + } + let rect = CGRect( x: superRect.origin.x, y: titleHeight, width: superRect.size.width, - height: superRect.size.height - titleHeight - selectedLineHeight + height: height ) return rect } @@ -597,11 +686,17 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty - returns: The rectangle that the placeholder should render in */ override open func placeholderRect(forBounds bounds: CGRect) -> CGRect { + var height = bounds.size.height - titleHeight() - selectedLineHeight + + if errorMessagePlacement == .bottomPlacement { + height = height - errorHeight() + } + let rect = CGRect( x: 0, y: titleHeight(), width: bounds.size.width, - height: bounds.size.height - titleHeight() - selectedLineHeight + height: height ) return rect } @@ -621,6 +716,27 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty return CGRect(x: 0, y: titleHeight(), width: bounds.size.width, height: titleHeight()) } + /** + Calculate the bounds for the error label. Override to create a custom size error field. + - parameter bounds: The current bounds of the title + - parameter editing: True if the control is selected or highlighted + - returns: The rectangle that the title label should render in + */ + open func errorLabelRectForBounds(_ bounds: CGRect, editing: Bool) -> CGRect { + if errorMessagePlacement == .defaultPlacement { + return CGRect.zero + } + else { + let lineRect = lineViewRectForBounds(bounds, editing: editing) + + if editing { + return CGRect(x: 0, y: lineRect.origin.y + selectedLineHeight, width: bounds.size.width, height: errorHeight()) + } + + return CGRect(x: 0, y: lineRect.origin.y + selectedLineHeight + errorHeight(), width: bounds.size.width, height: errorHeight()) + } + } + /** Calculate the bounds for the bottom line of the control. Override to create a custom size bottom line in the textbox. @@ -630,7 +746,13 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty */ open func lineViewRectForBounds(_ bounds: CGRect, editing: Bool) -> CGRect { let height = editing ? selectedLineHeight : lineHeight - return CGRect(x: 0, y: bounds.size.height - height, width: bounds.size.width, height: height) + + if errorMessagePlacement == .bottomPlacement { + return CGRect(x: 0, y: textRect(forBounds: bounds).maxY, width: bounds.size.width, height: height) + } + else { + return CGRect(x: 0, y: bounds.size.height - height, width: bounds.size.width, height: height) + } } /** @@ -645,6 +767,18 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty return 15.0 } + /** + Calculate the height of the error label. + -returns: the calculated height of the error label. Override to size the error with a different height + */ + open func errorHeight() -> CGFloat { + if let errorLabel = errorLabel, + let font = errorLabel.font { + return font.lineHeight + } + return 15.0 + } + /** Calcualte the height of the textfield. -returns: the calculated height of the textfield. Override to size the textfield with a different height @@ -678,6 +812,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty super.layoutSubviews() titleLabel.frame = titleLabelRectForBounds(bounds, editing: isTitleVisible() || _renderingInInterfaceBuilder) + errorLabel.frame = errorLabelRectForBounds(bounds, editing: isErrorVisible() || _renderingInInterfaceBuilder) lineView.frame = lineViewRectForBounds(bounds, editing: editingOrSelected || _renderingInInterfaceBuilder) } @@ -687,7 +822,12 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty - returns: the content size to be used for auto layout */ override open var intrinsicContentSize: CGSize { - return CGSize(width: bounds.size.width, height: titleHeight() + textHeight()) + if errorMessagePlacement == .bottomPlacement { + return CGSize(width: bounds.size.width, height: titleHeight() + textHeight() + errorHeight()) + } + else { + return CGSize(width: bounds.size.width, height: titleHeight() + textHeight()) + } } // MARK: - Helpers From 43a9aff96f560aacfdf62210b46c398b5645999f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Spencer=20M=C3=BCller=20Diniz?= Date: Thu, 3 Jan 2019 11:18:16 -0200 Subject: [PATCH 02/11] Code clean-up. --- Sources/SkyFloatingLabelTextField.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Sources/SkyFloatingLabelTextField.swift b/Sources/SkyFloatingLabelTextField.swift index 296585f..2afc2cf 100644 --- a/Sources/SkyFloatingLabelTextField.swift +++ b/Sources/SkyFloatingLabelTextField.swift @@ -478,9 +478,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty if !isEnabled { titleLabel.textColor = disabledColor } else if hasErrorMessage && errorMessagePlacement == .defaultPlacement { - if errorMessagePlacement == .defaultPlacement { - titleLabel.textColor = titleErrorColor ?? errorColor - } + titleLabel.textColor = titleErrorColor ?? errorColor } else { if editingOrSelected || isHighlighted { titleLabel.textColor = selectedTitleColor From 0778c018d2fa22b10b6b26f56861734085744e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Spencer=20M=C3=BCller=20Diniz?= Date: Mon, 7 Jan 2019 11:37:03 -0200 Subject: [PATCH 03/11] Added errorMessageAlignment option. --- Sources/SkyFloatingLabelTextField.swift | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Sources/SkyFloatingLabelTextField.swift b/Sources/SkyFloatingLabelTextField.swift index 2afc2cf..64a58cf 100644 --- a/Sources/SkyFloatingLabelTextField.swift +++ b/Sources/SkyFloatingLabelTextField.swift @@ -35,9 +35,16 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty if isLTRLanguage { textAlignment = .left titleLabel.textAlignment = .left + errorLabel.textAlignment = .left } else { textAlignment = .right titleLabel.textAlignment = .right + titleLabel.textAlignment = .right + } + + //Override error message default alignment + if let errorMessageAlignment = errorMessageAlignment { + errorLabel.textAlignment = errorMessageAlignment } } @@ -78,7 +85,18 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty } } - open var errorMessagePlacement: ErrorLabelPlacement = .defaultPlacement + open var errorMessagePlacement: ErrorLabelPlacement = .defaultPlacement { + didSet { + updateControl() + updatePlaceholder() + } + } + + open var errorMessageAlignment: NSTextAlignment? { + didSet { + updateTextAligment() + } + } fileprivate func updatePlaceholder() { guard let placeholder = placeholder, let font = placeholderFont ?? font else { From c228a9cbf2d4da916a2192e1686c867b82dbbfbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Spencer=20M=C3=BCller=20Diniz?= Date: Mon, 18 Feb 2019 15:55:08 -0300 Subject: [PATCH 04/11] Added comments for new public/open vars. --- Sources/SkyFloatingLabelTextField.swift | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Sources/SkyFloatingLabelTextField.swift b/Sources/SkyFloatingLabelTextField.swift index 64a58cf..05353d9 100644 --- a/Sources/SkyFloatingLabelTextField.swift +++ b/Sources/SkyFloatingLabelTextField.swift @@ -11,6 +11,11 @@ import UIKit +/** + An enum for the possible error labe placements. + .defaultPlacement is the standard (on top) position + .bottomPlacement positions error label below the text field. + */ public enum ErrorLabelPlacement { case defaultPlacement case bottomPlacement @@ -84,14 +89,16 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty updatePlaceholder() } } - + + /// A ErrorLabelPlacement value that determines where the error label will be placed. open var errorMessagePlacement: ErrorLabelPlacement = .defaultPlacement { didSet { updateControl() updatePlaceholder() } } - + + // An NSTextAlignment value that determines the error message alignment. open var errorMessageAlignment: NSTextAlignment? { didSet { updateTextAligment() @@ -221,6 +228,8 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty /// The internal `UILabel` that displays the selected, deselected title or error message based on the current state. open var titleLabel: UILabel! + + /// The internal `UILabel` that displays error messsage if errorMessagePlacement is .bottomPlacement. open var errorLabel: UILabel! // MARK: Properties From e008447ee1139717c0f9e234c31dd5b4b3fc4a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Spencer=20M=C3=BCller=20Diniz?= Date: Mon, 18 Feb 2019 15:59:46 -0300 Subject: [PATCH 05/11] Fixed errorLabel.textAlignment. --- Sources/SkyFloatingLabelTextField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SkyFloatingLabelTextField.swift b/Sources/SkyFloatingLabelTextField.swift index 05353d9..f75cec2 100644 --- a/Sources/SkyFloatingLabelTextField.swift +++ b/Sources/SkyFloatingLabelTextField.swift @@ -44,7 +44,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty } else { textAlignment = .right titleLabel.textAlignment = .right - titleLabel.textAlignment = .right + errorLabel.textAlignment = .right } //Override error message default alignment From 348a5560c61ec426f38ed2dcb3e296ec3dda21c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Spencer=20M=C3=BCller=20Diniz?= Date: Mon, 18 Feb 2019 16:13:24 -0300 Subject: [PATCH 06/11] Added updateErrorLabelColor to updateColors. --- Sources/SkyFloatingLabelTextField.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Sources/SkyFloatingLabelTextField.swift b/Sources/SkyFloatingLabelTextField.swift index f75cec2..a4d0f81 100644 --- a/Sources/SkyFloatingLabelTextField.swift +++ b/Sources/SkyFloatingLabelTextField.swift @@ -481,6 +481,11 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty updateLineColor() updateTitleColor() updateTextColor() + updateErrorLabelColor() + } + + fileprivate func updateErrorLabelColor() { + errorLabel.textColor = errorColor } fileprivate func updateLineColor() { From 8f9f2adc5752386f3000b14920bea1f121209b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Spencer=20M=C3=BCller=20Diniz?= Date: Mon, 18 Feb 2019 16:17:21 -0300 Subject: [PATCH 07/11] Fixed comment about errorColor property. --- Sources/SkyFloatingLabelTextField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/SkyFloatingLabelTextField.swift b/Sources/SkyFloatingLabelTextField.swift index a4d0f81..ecac6d5 100644 --- a/Sources/SkyFloatingLabelTextField.swift +++ b/Sources/SkyFloatingLabelTextField.swift @@ -153,7 +153,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty } } - /// A UIColor value that determines the color used for the title label and line when the error message is not `nil` + /// A UIColor value that determines the color used for the error label @IBInspectable dynamic open var errorColor: UIColor = .red { didSet { updateColors() From 807edec02e851e9681a57ea9ef382700650c2260 Mon Sep 17 00:00:00 2001 From: Jared Egan Date: Mon, 18 Feb 2019 15:49:59 -0500 Subject: [PATCH 08/11] ErrorMessagePlacement: Changed some symbol names to be more Swifty, added unit tests, adjust syntax to be consistent with project --- .../SkyFloatingLabelTextFieldTests.swift | 49 ++++++++++++++ Sources/SkyFloatingLabelTextField.swift | 65 +++++++++---------- 2 files changed, 79 insertions(+), 35 deletions(-) diff --git a/SkyFloatingLabelTextField/SkyFloatingLabelTextFieldTests/SkyFloatingLabelTextFieldTests.swift b/SkyFloatingLabelTextField/SkyFloatingLabelTextFieldTests/SkyFloatingLabelTextFieldTests.swift index e692d7d..45e7544 100644 --- a/SkyFloatingLabelTextField/SkyFloatingLabelTextFieldTests/SkyFloatingLabelTextFieldTests.swift +++ b/SkyFloatingLabelTextField/SkyFloatingLabelTextFieldTests/SkyFloatingLabelTextFieldTests.swift @@ -187,6 +187,19 @@ class SkyFloatingLabelTextFieldTests: XCTestCase { // swiftlint:disable:this typ XCTAssertEqual(floatingLabelTextField.lineView.backgroundColor, self.customColor) } + func test_whenSettingErrorColor_withErrorMessagePlacementIsBottom_thenErrorLabelTextColorIsChangedToThisColor() { + // given + floatingLabelTextField.errorMessagePlacement = .bottom + floatingLabelTextField.errorMessage = "test" + + // when + floatingLabelTextField.errorColor = self.customColor + + // then + XCTAssertNotEqual(floatingLabelTextField.titleLabel.textColor, self.customColor) + XCTAssertEqual(floatingLabelTextField.errorLabel.textColor, self.customColor) + } + func test_whenSettingSelectedTitleColor_withTextfieldBeingSelected_thenTitleLabelTextColorIsChangedToThisColor() { // given floatingLabelTextField.isSelected = true @@ -895,6 +908,42 @@ class SkyFloatingLabelTextFieldTests: XCTestCase { // swiftlint:disable:this typ XCTAssertEqual(size.height, floatingLabelTextField.titleHeight() + floatingLabelTextField.textHeight()) } + // MARK: Error Message Placement + func test_whenSettingErrorMessage_whenErrorMessagePlacementSetToDefault_thenTitleLabelTextIsChanged() { + // given + XCTAssertEqual(floatingLabelTextField.errorMessagePlacement, .default) + + // when + floatingLabelTextField.errorMessage = "SAMPLE ERROR" + + // then + XCTAssertEqual(floatingLabelTextField.titleLabel.text, "SAMPLE ERROR") + } + + func test_whenSettingErrorMessage_whenErrorMessagePlacementSetToBottom_thenErrorLabelTextIsChanged() { + // given + floatingLabelTextField.title = "SAMPLE TITLE" + floatingLabelTextField.errorMessagePlacement = .bottom + + // when + floatingLabelTextField.errorMessage = "SAMPLE ERROR" + + // then + XCTAssertEqual(floatingLabelTextField.titleLabel.text, "SAMPLE TITLE") + XCTAssertEqual(floatingLabelTextField.errorLabel.text, "SAMPLE ERROR") + } + + func test_whenErrorLabelAlignment_thenErrorLabelTextAlignemntIsChanged() { + // given + XCTAssertNotEqual(floatingLabelTextField.errorLabel.textAlignment, .center) + + // when + floatingLabelTextField.errorLabelAlignment = .center + + // then + XCTAssertEqual(floatingLabelTextField.errorLabel.textAlignment, .center) + } + // MARK: - Helpers func failOnTimeoutAfterSeconds(_ timeout: TimeInterval) { diff --git a/Sources/SkyFloatingLabelTextField.swift b/Sources/SkyFloatingLabelTextField.swift index ecac6d5..3aa9974 100644 --- a/Sources/SkyFloatingLabelTextField.swift +++ b/Sources/SkyFloatingLabelTextField.swift @@ -12,13 +12,13 @@ import UIKit /** - An enum for the possible error labe placements. - .defaultPlacement is the standard (on top) position - .bottomPlacement positions error label below the text field. + An enum for the possible error label placements. + .default is the standard (on top) position; the error message is displayed in the `titleLabel`. + .bottom displays the error below the text field in a dedicated `errorLabel`. */ -public enum ErrorLabelPlacement { - case defaultPlacement - case bottomPlacement +public enum ErrorMessagePlacement { + case `default` + case bottom } /** @@ -47,9 +47,9 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty errorLabel.textAlignment = .right } - //Override error message default alignment - if let errorMessageAlignment = errorMessageAlignment { - errorLabel.textAlignment = errorMessageAlignment + // Override error message default alignment + if let errorLabelAlignment = errorLabelAlignment { + errorLabel.textAlignment = errorLabelAlignment } } @@ -90,16 +90,16 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty } } - /// A ErrorLabelPlacement value that determines where the error label will be placed. - open var errorMessagePlacement: ErrorLabelPlacement = .defaultPlacement { + /// A `ErrorMessagePlacement` value that determines where the error message will be displayed. + open var errorMessagePlacement: ErrorMessagePlacement = .default { didSet { updateControl() updatePlaceholder() } } - // An NSTextAlignment value that determines the error message alignment. - open var errorMessageAlignment: NSTextAlignment? { + /// An `NSTextAlignment` value that determines the error label text alignment. + open var errorLabelAlignment: NSTextAlignment? { didSet { updateTextAligment() } @@ -153,7 +153,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty } } - /// A UIColor value that determines the color used for the error label + /// A UIColor value that determines the color used for the label displaying the error message @IBInspectable dynamic open var errorColor: UIColor = .red { didSet { updateColors() @@ -229,7 +229,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty /// The internal `UILabel` that displays the selected, deselected title or error message based on the current state. open var titleLabel: UILabel! - /// The internal `UILabel` that displays error messsage if errorMessagePlacement is .bottomPlacement. + /// The internal `UILabel` that displays error messsage if `errorMessagePlacement` is `.bottom`. open var errorLabel: UILabel! // MARK: Properties @@ -509,7 +509,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty if !isEnabled { titleLabel.textColor = disabledColor - } else if hasErrorMessage && errorMessagePlacement == .defaultPlacement { + } else if hasErrorMessage && errorMessagePlacement == .default { titleLabel.textColor = titleErrorColor ?? errorColor } else { if editingOrSelected || isHighlighted { @@ -540,7 +540,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty var titleText: String? var errorText: String? - if errorMessagePlacement == .defaultPlacement { + if errorMessagePlacement == .default { if hasErrorMessage { titleText = titleFormatter(errorMessage!) } else { @@ -553,8 +553,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty titleText = titleOrPlaceholder() } } - } - else { + } else { if hasErrorMessage { errorText = titleFormatter(errorMessage!) } @@ -602,10 +601,9 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty - returns: True if the title is displayed on the control, false otherwise. */ open func isTitleVisible() -> Bool { - if errorMessagePlacement == .defaultPlacement { + if errorMessagePlacement == .default { return hasText || hasErrorMessage || _titleVisible - } - else { + } else { return hasText || _titleVisible } } @@ -673,7 +671,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty var height = superRect.size.height - titleHeight - selectedLineHeight - if errorMessagePlacement == .bottomPlacement { + if errorMessagePlacement == .bottom { height = height - errorHeight() } @@ -697,7 +695,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty var height = superRect.size.height - titleHeight - selectedLineHeight - if errorMessagePlacement == .bottomPlacement { + if errorMessagePlacement == .bottom { height = height - errorHeight() } @@ -718,7 +716,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty override open func placeholderRect(forBounds bounds: CGRect) -> CGRect { var height = bounds.size.height - titleHeight() - selectedLineHeight - if errorMessagePlacement == .bottomPlacement { + if errorMessagePlacement == .bottom { height = height - errorHeight() } @@ -753,10 +751,9 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty - returns: The rectangle that the title label should render in */ open func errorLabelRectForBounds(_ bounds: CGRect, editing: Bool) -> CGRect { - if errorMessagePlacement == .defaultPlacement { + if errorMessagePlacement == .default { return CGRect.zero - } - else { + } else { let lineRect = lineViewRectForBounds(bounds, editing: editing) if editing { @@ -777,10 +774,9 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty open func lineViewRectForBounds(_ bounds: CGRect, editing: Bool) -> CGRect { let height = editing ? selectedLineHeight : lineHeight - if errorMessagePlacement == .bottomPlacement { + if errorMessagePlacement == .bottom { return CGRect(x: 0, y: textRect(forBounds: bounds).maxY, width: bounds.size.width, height: height) - } - else { + } else { return CGRect(x: 0, y: bounds.size.height - height, width: bounds.size.width, height: height) } } @@ -810,7 +806,7 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty } /** - Calcualte the height of the textfield. + Calculate the height of the textfield. -returns: the calculated height of the textfield. Override to size the textfield with a different height */ open func textHeight() -> CGFloat { @@ -852,10 +848,9 @@ open class SkyFloatingLabelTextField: UITextField { // swiftlint:disable:this ty - returns: the content size to be used for auto layout */ override open var intrinsicContentSize: CGSize { - if errorMessagePlacement == .bottomPlacement { + if errorMessagePlacement == .bottom { return CGSize(width: bounds.size.width, height: titleHeight() + textHeight() + errorHeight()) - } - else { + } else { return CGSize(width: bounds.size.width, height: titleHeight() + textHeight()) } } From f83f1bc2cb83f60d7738510f863d2575cc6203b8 Mon Sep 17 00:00:00 2001 From: Eder Andrade Date: Fri, 3 May 2019 14:29:27 -0300 Subject: [PATCH 09/11] Add example of "errorMessagePlacement" property at the "Setting text properties" test screen --- .../Base.lproj/Main.storyboard | 463 +++++++++++------- .../Example1/SettingTextsViewController.swift | 11 + 2 files changed, 293 insertions(+), 181 deletions(-) diff --git a/SkyFloatingLabelTextField/SkyFloatingLabelTextFieldExample/Base.lproj/Main.storyboard b/SkyFloatingLabelTextField/SkyFloatingLabelTextFieldExample/Base.lproj/Main.storyboard index feeba03..89f347f 100644 --- a/SkyFloatingLabelTextField/SkyFloatingLabelTextFieldExample/Base.lproj/Main.storyboard +++ b/SkyFloatingLabelTextField/SkyFloatingLabelTextFieldExample/Base.lproj/Main.storyboard @@ -1,13 +1,11 @@ - + - - - + @@ -24,10 +22,10 @@ - + - + @@ -36,159 +34,262 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - + @@ -233,14 +334,14 @@ - + - + @@ -263,13 +364,13 @@ - + @@ -281,13 +382,13 @@ - + @@ -299,19 +400,19 @@ - + @@ -345,10 +446,10 @@ - + - + @@ -360,13 +461,13 @@ - + @@ -378,13 +479,13 @@ - + @@ -396,19 +497,19 @@ - + @@ -439,7 +540,7 @@ - - + - + @@ -721,7 +822,7 @@ - + @@ -730,8 +831,8 @@ - - -