Skip to content

Commit

Permalink
FieldRow.titlePercentage instead of FieldRow.textFieldPercentage (xma…
Browse files Browse the repository at this point in the history
…rtlabs#965). Properly calculate FieldRow constraints.

* Deprecate FieldRowConformance.textFieldPercentage in favor of FieldRowConformance.titleLabelPercentage in order to fix alignment issues when using an accessory view/type on a FieldCell

* Include optional imageView in title width calculations. Only works for right-to-left languages in iOS 9.0 and higher since only app extension API is allowed. This prohibits determining of interface layout direction in older iOS versions.

* Rename titleLabelPercentage to titlePercentage as it should not only encompass the titleLabel’s width but also an optional imageView’s width. Also maintain a private calculatedTitlePercentage property instead of caching and resetting the row’s value after each constraint update.

If `titleFieldPercentage` is not set, the layout is not adjusted to make
up for potential accessory and/or image views. Instead a fixed constant
is used for the respective constraint. By moving this fixed constant to
the advanced layout calculation we not only solve the aforementioned
issue but also eliminate duplication of the the constant during
constraint setup.

Note that this could have also been achieved by simply declaring
`titleFieldPercentage` a non-optional variable and assigning a default
value of 0.3. Since this would represent both a code breaking as well as
somewhat of a semantic change the solution at hand was deemed preferable
  • Loading branch information
quiekedei authored and Martin Barreto committed Jul 28, 2017
1 parent f68d755 commit bc1662d
Showing 1 changed file with 64 additions and 27 deletions.
91 changes: 64 additions & 27 deletions Source/Rows/Common/FieldRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ public protocol InputTypeInitiable {
init?(string stringValue: String)
}

public protocol FieldRowConformance: FormatterConformance {
var textFieldPercentage: CGFloat? { get set }
var placeholder: String? { get set }
var placeholderColor: UIColor? { get set }
public protocol FieldRowConformance : FormatterConformance {
var titlePercentage : CGFloat? { get set }
var placeholder : String? { get set }
var placeholderColor : UIColor? { get set }
}

extension Int: InputTypeInitiable {
Expand Down Expand Up @@ -86,8 +86,19 @@ open class FieldRow<Cell: CellType>: FormatteableRow<Cell>, FieldRowConformance,
open var keyboardReturnType: KeyboardReturnTypeConfiguration?

/// The percentage of the cell that should be occupied by the textField
open var textFieldPercentage: CGFloat?

@available (*, deprecated, message: "Use titleLabelPercentage instead")
open var textFieldPercentage : CGFloat? {
get {
return titlePercentage.map { 1 - $0 }
}
set {
titlePercentage = newValue.map { 1 - $0 }
}
}

/// The percentage of the cell that should be occupied by the title (i.e. the titleLabel and optional imageView combined)
open var titlePercentage: CGFloat?

/// The placeholder for the textField
open var placeholder: String?

Expand Down Expand Up @@ -126,7 +137,9 @@ open class _FieldCell<T> : Cell<T>, UITextFieldDelegate, TextFieldCell where T:
private var awakeFromNibCalled = false

open var dynamicConstraints = [NSLayoutConstraint]()


private var calculatedTitlePercentage: CGFloat = 0.7

public required init(style: UITableViewCellStyle, reuseIdentifier: String?) {

let textField = UITextField()
Expand Down Expand Up @@ -269,28 +282,31 @@ open class _FieldCell<T> : Cell<T>, UITextFieldDelegate, TextFieldCell where T:
if let titleLabel = titleLabel, let text = titleLabel.text, !text.isEmpty {
views["label"] = titleLabel
dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: "H:[imageView]-(15)-[label]-[textField]-|", options: NSLayoutFormatOptions(), metrics: nil, views: views)
dynamicConstraints.append(NSLayoutConstraint(item: textField,
attribute: .width,
relatedBy: (row as? FieldRowConformance)?.textFieldPercentage != nil ? .equal : .greaterThanOrEqual,
toItem: contentView,
attribute: .width,
multiplier: (row as? FieldRowConformance)?.textFieldPercentage ?? 0.3,
constant: 0.0))
} else {
dynamicConstraints.append(NSLayoutConstraint(item: titleLabel,
attribute: .width,
relatedBy: (row as? FieldRowConformance)?.titlePercentage != nil ? .equal : .lessThanOrEqual,
toItem: contentView,
attribute: .width,
multiplier: calculatedTitlePercentage,
constant: 0.0))
}
else{
dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: "H:[imageView]-(15)-[textField]-|", options: [], metrics: nil, views: views)
}
} else {
if let titleLabel = titleLabel, let text = titleLabel.text, !text.isEmpty {
}
else{
if let titleLabel = titleLabel, let text = titleLabel.text, !text.isEmpty {
views["label"] = titleLabel
dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|-[label]-[textField]-|", options: [], metrics: nil, views: views)
dynamicConstraints.append(NSLayoutConstraint(item: textField,
attribute: .width,
relatedBy: (row as? FieldRowConformance)?.textFieldPercentage != nil ? .equal : .greaterThanOrEqual,
toItem: contentView,
attribute: .width,
multiplier: (row as? FieldRowConformance)?.textFieldPercentage ?? 0.3,
constant: 0.0))
} else {
dynamicConstraints.append(NSLayoutConstraint(item: titleLabel,
attribute: .width,
relatedBy: (row as? FieldRowConformance)?.titlePercentage != nil ? .equal : .lessThanOrEqual,
toItem: contentView,
attribute: .width,
multiplier: calculatedTitlePercentage,
constant: 0.0))
}
else{
dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|-[textField]-|", options: .alignAllLeft, metrics: nil, views: views)
}
}
Expand Down Expand Up @@ -382,6 +398,27 @@ open class _FieldCell<T> : Cell<T>, UITextFieldDelegate, TextFieldCell where T:

open func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
return formViewController()?.textInputShouldEndEditing(textField, cell: self) ?? true
}

}

open override func layoutSubviews() {
super.layoutSubviews()
guard let row = (row as? FieldRowConformance) else { return }
guard let titlePercentage = row.titlePercentage else { return }
var targetTitleWidth = bounds.size.width * titlePercentage
if let imageView = imageView, let _ = imageView.image, let titleLabel = titleLabel {
var extraWidthToSubtract = titleLabel.frame.minX - imageView.frame.minX // Left-to-right interface layout
if #available(iOS 9.0, *) {
if UIView.userInterfaceLayoutDirection(for: self.semanticContentAttribute) == .rightToLeft {
extraWidthToSubtract = imageView.frame.maxX - titleLabel.frame.maxX
}
}
targetTitleWidth -= extraWidthToSubtract
}
let targetTitlePercentage = targetTitleWidth / contentView.bounds.size.width
if calculatedTitlePercentage != targetTitlePercentage {
calculatedTitlePercentage = targetTitlePercentage
setNeedsUpdateConstraints()
updateConstraintsIfNeeded()
}
}
}

0 comments on commit bc1662d

Please sign in to comment.