Commit 6f688295 by Daniel Dahan

Merge branch 'development' into editor

parents 689434d3 d8ec48b9
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'Material' s.name = 'Material'
s.version = '2.3.2' s.version = '2.3.4'
s.license = 'BSD-3-Clause' s.license = 'BSD-3-Clause'
s.summary = 'Material is an animation and graphics framework that is used to create beautiful applications.' s.summary = 'Material is an animation and graphics framework that is used to create beautiful applications.'
s.homepage = 'http://materialswift.com' s.homepage = 'http://materialswift.com'
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>FMWK</string> <string>FMWK</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2.3.2</string> <string>2.3.4</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
......
...@@ -35,8 +35,8 @@ open class ErrorTextField: TextField { ...@@ -35,8 +35,8 @@ open class ErrorTextField: TextField {
@IBInspectable @IBInspectable
open var isErrorRevealed = false { open var isErrorRevealed = false {
didSet { didSet {
layoutDetailLabel()
detailLabel.isHidden = !isErrorRevealed detailLabel.isHidden = !isErrorRevealed
layoutSubviews()
} }
} }
......
...@@ -37,70 +37,40 @@ public enum GridAxisDirection: Int { ...@@ -37,70 +37,40 @@ public enum GridAxisDirection: Int {
case vertical case vertical
} }
public class GridAxis { public struct GridAxis {
/// Grid reference.
unowned var grid: Grid
/// The direction the grid lays its views out. /// The direction the grid lays its views out.
open var direction: GridAxisDirection = .horizontal { var direction = GridAxisDirection.horizontal
didSet {
grid.reload()
}
}
/// The rows size. /// The rows size.
public var rows: Int { public var rows: Int
didSet {
grid.reload()
}
}
/// The columns size. /// The columns size.
public var columns: Int { public var columns: Int
didSet {
grid.reload()
}
}
/** /**
Initializer. Initializer.
- Parameter grid: The Grid reference used for offset values.
- Parameter rows: The number of rows, vertical axis the grid will use. - Parameter rows: The number of rows, vertical axis the grid will use.
- Parameter columns: The number of columns, horizontal axis the grid will use. - Parameter columns: The number of columns, horizontal axis the grid will use.
*/ */
public init(grid: Grid, rows: Int = 12, columns: Int = 12) { public init(rows: Int = 12, columns: Int = 12) {
self.grid = grid
self.rows = rows self.rows = rows
self.columns = columns self.columns = columns
} }
} }
public class GridOffset { public struct GridOffset {
/// Grid reference.
unowned var grid: Grid
/// The rows size. /// The rows size.
public var rows: Int { public var rows: Int
didSet {
grid.reload()
}
}
/// The columns size. /// The columns size.
public var columns: Int { public var columns: Int
didSet {
grid.reload()
}
}
/** /**
Initializer. Initializer.
- Parameter grid: The Grid reference used for offset values.
- Parameter rows: The number of rows, vertical axis the grid will use. - Parameter rows: The number of rows, vertical axis the grid will use.
- Parameter columns: The number of columns, horizontal axis the grid will use. - Parameter columns: The number of columns, horizontal axis the grid will use.
*/ */
public init(grid: Grid, rows: Int = 0, columns: Int = 0) { public init(rows: Int = 0, columns: Int = 0) {
self.grid = grid
self.rows = rows self.rows = rows
self.columns = columns self.columns = columns
} }
...@@ -128,10 +98,18 @@ public class Grid { ...@@ -128,10 +98,18 @@ public class Grid {
} }
/// Offsets for rows and columns. /// Offsets for rows and columns.
public private(set) var offset: GridOffset! public var offset = GridOffset() {
didSet {
reload()
}
}
/// The axis in which the Grid is laying out its views. /// The axis in which the Grid is laying out its views.
public private(set) var axis: GridAxis! public var axis = GridAxis() {
didSet {
reload()
}
}
/// Preset inset value for grid. /// Preset inset value for grid.
public var layoutEdgeInsetsPreset = EdgeInsetsPreset.none { public var layoutEdgeInsetsPreset = EdgeInsetsPreset.none {
...@@ -178,6 +156,9 @@ public class Grid { ...@@ -178,6 +156,9 @@ public class Grid {
/// An Array of UIButtons. /// An Array of UIButtons.
public var views = [UIView]() { public var views = [UIView]() {
didSet { didSet {
for v in oldValue {
v.removeFromSuperview()
}
reload() reload()
} }
} }
...@@ -193,8 +174,6 @@ public class Grid { ...@@ -193,8 +174,6 @@ public class Grid {
self.rows = rows self.rows = rows
self.columns = columns self.columns = columns
self.interimSpace = interimSpace self.interimSpace = interimSpace
offset = GridOffset(grid: self)
axis = GridAxis(grid: self)
} }
/// Begins a deferred block. /// Begins a deferred block.
...@@ -214,6 +193,14 @@ public class Grid { ...@@ -214,6 +193,14 @@ public class Grid {
return return
} }
guard let canvas = context else {
return
}
guard 0 < canvas.width && 0 < canvas.height else {
return
}
let count = views.count let count = views.count
guard 0 < count else { guard 0 < count else {
...@@ -224,14 +211,6 @@ public class Grid { ...@@ -224,14 +211,6 @@ public class Grid {
var i = 0 var i = 0
for v in views { for v in views {
guard let canvas = context else {
return
}
guard 0 < canvas.width && 0 < canvas.height else {
return
}
if canvas != v.superview { if canvas != v.superview {
v.removeFromSuperview() v.removeFromSuperview()
canvas.addSubview(v) canvas.addSubview(v)
......
...@@ -36,11 +36,11 @@ ...@@ -36,11 +36,11 @@
- Returns: The associated reference for the initializer object. - Returns: The associated reference for the initializer object.
*/ */
internal func AssociatedObject<T: Any>(base: Any, key: UnsafePointer<UInt8>, initializer: () -> T) -> T { internal func AssociatedObject<T: Any>(base: Any, key: UnsafePointer<UInt8>, initializer: () -> T) -> T {
if let v: T = objc_getAssociatedObject(base, key) as? T { if let v = objc_getAssociatedObject(base, key) as? T {
return v return v
} }
let v: T = initializer() let v = initializer()
objc_setAssociatedObject(base, key, v, .OBJC_ASSOCIATION_RETAIN) objc_setAssociatedObject(base, key, v, .OBJC_ASSOCIATION_RETAIN)
return v return v
} }
......
...@@ -103,7 +103,7 @@ open class PageTabBarController: RootController { ...@@ -103,7 +103,7 @@ open class PageTabBarController: RootController {
/// Reference to the PageTabBar. /// Reference to the PageTabBar.
open private(set) lazy var pageTabBar: PageTabBar = PageTabBar() open private(set) lazy var pageTabBar: PageTabBar = PageTabBar()
/// A boolean that indicates whether bounds is enabled. /// A boolean that indicates whether bounce is enabled.
open var isBounceEnabled: Bool { open var isBounceEnabled: Bool {
didSet { didSet {
scrollView?.bounces = isBounceEnabled scrollView?.bounces = isBounceEnabled
......
...@@ -103,12 +103,28 @@ open class TextField: UITextField { ...@@ -103,12 +103,28 @@ open class TextField: UITextField {
/// Divider normal height. /// Divider normal height.
@IBInspectable @IBInspectable
open var dividerNormalHeight: CGFloat = 1 open var dividerNormalHeight: CGFloat = 1 {
didSet {
guard !isEditing else {
return
}
dividerThickness = dividerNormalHeight
}
}
/// Divider active height. /// Divider active height.
@IBInspectable @IBInspectable
open var dividerActiveHeight: CGFloat = 2 open var dividerActiveHeight: CGFloat = 2 {
didSet {
guard isEditing else {
return
}
dividerThickness = dividerActiveHeight
}
}
/// Divider normal color. /// Divider normal color.
@IBInspectable @IBInspectable
...@@ -142,22 +158,6 @@ open class TextField: UITextField { ...@@ -142,22 +158,6 @@ open class TextField: UITextField {
} }
} }
/// TextField's text property observer.
@IBInspectable
open override var text: String? {
didSet {
guard isEmpty else {
return
}
guard !isFirstResponder else {
return
}
placeholderEditingDidEndAnimation()
}
}
/// The placeholderLabel text value. /// The placeholderLabel text value.
@IBInspectable @IBInspectable
open override var placeholder: String? { open override var placeholder: String? {
...@@ -388,56 +388,6 @@ open class TextField: UITextField { ...@@ -388,56 +388,6 @@ open class TextField: UITextField {
layoutShape() layoutShape()
} }
/// Handles the text editing did begin state.
@objc
open func handleEditingDidBegin() {
placeholderEditingDidBeginAnimation()
dividerEditingDidBeginAnimation()
}
// Live updates the textField text.
@objc
internal func handleEditingChanged(textField: UITextField) {
(delegate as? TextFieldDelegate)?.textField?(textField: self, didChange: textField.text)
}
/// Handles the text editing did end state.
@objc
open func handleEditingDidEnd() {
placeholderEditingDidEndAnimation()
dividerEditingDidEndAnimation()
}
/// Handles the clearIconButton TouchUpInside event.
@objc
open func handleClearIconButton() {
guard nil == delegate?.textFieldShouldClear || true == delegate?.textFieldShouldClear?(self) else {
return
}
let t = text
(delegate as? TextFieldDelegate)?.textField?(textField: self, willClear: t)
text = nil
(delegate as? TextFieldDelegate)?.textField?(textField: self, didClear: t)
}
/// Handles the visibilityIconButton TouchUpInside event.
@objc
open func handleVisibilityIconButton() {
isSecureTextEntry = !isSecureTextEntry
if !isSecureTextEntry {
super.font = nil
font = placeholderLabel.font
}
visibilityIconButton?.tintColor = visibilityIconButton?.tintColor.withAlphaComponent(isSecureTextEntry ? 0.38 : 0.54)
}
/** /**
Prepares the view instance when intialized. When subclassing, Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepare method it is recommended to override the prepare method
...@@ -450,6 +400,7 @@ open class TextField: UITextField { ...@@ -450,6 +400,7 @@ open class TextField: UITextField {
borderStyle = .none borderStyle = .none
backgroundColor = nil backgroundColor = nil
contentScaleFactor = Device.scale contentScaleFactor = Device.scale
prepareDivider() prepareDivider()
preparePlaceholderLabel() preparePlaceholderLabel()
prepareDetailLabel() prepareDetailLabel()
...@@ -459,11 +410,7 @@ open class TextField: UITextField { ...@@ -459,11 +410,7 @@ open class TextField: UITextField {
/// Ensures that the components are sized correctly. /// Ensures that the components are sized correctly.
open func reload() { open func reload() {
guard willLayout else { guard willLayout && !isAnimating else {
return
}
guard !isAnimating else {
return return
} }
...@@ -474,9 +421,62 @@ open class TextField: UITextField { ...@@ -474,9 +421,62 @@ open class TextField: UITextField {
layoutDivider() layoutDivider()
layoutLeftView() layoutLeftView()
} }
}
extension TextField {
/// Prepares the divider.
fileprivate func prepareDivider() {
dividerColor = dividerNormalColor
}
/// Prepares the placeholderLabel.
fileprivate func preparePlaceholderLabel() {
font = RobotoFont.regular(with: 16)
placeholderNormalColor = Color.darkText.others
addSubview(placeholderLabel)
addObserver(self, forKeyPath: "placeholderLabel.text", options: [], context: &TextFieldContext)
}
/// Prepares the detailLabel.
fileprivate func prepareDetailLabel() {
detailLabel.font = RobotoFont.regular(with: 12)
detailLabel.numberOfLines = 0
detailColor = Color.darkText.others
addSubview(detailLabel)
addObserver(self, forKeyPath: "detailLabel.text", options: [], context: &TextFieldContext)
}
/// Prepares the leftView.
fileprivate func prepareLeftView() {
leftView?.contentMode = .left
}
/// Prepares the target handlers.
fileprivate func prepareTargetHandlers() {
addTarget(self, action: #selector(handleEditingDidBegin), for: .editingDidBegin)
addTarget(self, action: #selector(handleEditingChanged), for: .editingChanged)
addTarget(self, action: #selector(handleEditingDidEnd), for: .editingDidEnd)
}
/// Prepares the textAlignment.
fileprivate func prepareTextAlignment() {
textAlignment = .rightToLeft == UIApplication.shared.userInterfaceLayoutDirection ? .right : .left
}
/// Updates the placeholderLabel attributedText.
fileprivate func updatePlaceholderLabelColor() {
placeholderLabel.textColor = isEditing ? placeholderActiveColor : placeholderNormalColor
}
/// Updates the detailLabel attributedText.
fileprivate func updateDetailLabelColor() {
detailLabel.textColor = detailColor
}
}
extension TextField {
/// Layout the placeholderLabel. /// Layout the placeholderLabel.
open func layoutPlaceholderLabel() { fileprivate func layoutPlaceholderLabel() {
let w = leftViewWidth let w = leftViewWidth
let h = 0 == height ? intrinsicContentSize.height : height let h = 0 == height ? intrinsicContentSize.height : height
...@@ -501,7 +501,7 @@ open class TextField: UITextField { ...@@ -501,7 +501,7 @@ open class TextField: UITextField {
} }
/// Layout the detailLabel. /// Layout the detailLabel.
open func layoutDetailLabel() { fileprivate func layoutDetailLabel() {
let c = dividerContentEdgeInsets let c = dividerContentEdgeInsets
detailLabel.sizeToFit() detailLabel.sizeToFit()
detailLabel.x = c.left detailLabel.x = c.left
...@@ -510,7 +510,7 @@ open class TextField: UITextField { ...@@ -510,7 +510,7 @@ open class TextField: UITextField {
} }
/// Layout the a button. /// Layout the a button.
open func layoutButton(button: UIButton?) { fileprivate func layoutButton(button: UIButton?) {
guard 0 < width && 0 < height else { guard 0 < width && 0 < height else {
return return
} }
...@@ -519,12 +519,12 @@ open class TextField: UITextField { ...@@ -519,12 +519,12 @@ open class TextField: UITextField {
} }
/// Layout the divider. /// Layout the divider.
open func layoutDivider() { fileprivate func layoutDivider() {
divider.reload() divider.reload()
} }
/// Layout the leftView. /// Layout the leftView.
open func layoutLeftView() { fileprivate func layoutLeftView() {
guard let v = leftView else { guard let v = leftView else {
return return
} }
...@@ -533,21 +533,77 @@ open class TextField: UITextField { ...@@ -533,21 +533,77 @@ open class TextField: UITextField {
v.frame = CGRect(x: 0, y: 0, width: w, height: height) v.frame = CGRect(x: 0, y: 0, width: w, height: height)
dividerContentEdgeInsets.left = w dividerContentEdgeInsets.left = w
} }
}
extension TextField {
/// Handles the text editing did begin state.
@objc
fileprivate func handleEditingDidBegin() {
placeholderEditingDidBeginAnimation()
dividerEditingDidBeginAnimation()
}
// Live updates the textField text.
@objc
fileprivate func handleEditingChanged(textField: UITextField) {
(delegate as? TextFieldDelegate)?.textField?(textField: self, didChange: textField.text)
}
/// Handles the text editing did end state.
@objc
fileprivate func handleEditingDidEnd() {
placeholderEditingDidEndAnimation()
dividerEditingDidEndAnimation()
}
/// Handles the clearIconButton TouchUpInside event.
@objc
fileprivate func handleClearIconButton() {
guard nil == delegate?.textFieldShouldClear || true == delegate?.textFieldShouldClear?(self) else {
return
}
let t = text
(delegate as? TextFieldDelegate)?.textField?(textField: self, willClear: t)
text = nil
(delegate as? TextFieldDelegate)?.textField?(textField: self, didClear: t)
}
/// Handles the visibilityIconButton TouchUpInside event.
@objc
fileprivate func handleVisibilityIconButton() {
isSecureTextEntry = !isSecureTextEntry
if !isSecureTextEntry {
super.font = nil
font = placeholderLabel.font
}
visibilityIconButton?.tintColor = visibilityIconButton?.tintColor.withAlphaComponent(isSecureTextEntry ? 0.38 : 0.54)
}
}
extension TextField {
/// The animation for the divider when editing begins. /// The animation for the divider when editing begins.
open func dividerEditingDidBeginAnimation() { fileprivate func dividerEditingDidBeginAnimation() {
dividerThickness = dividerActiveHeight dividerThickness = dividerActiveHeight
dividerColor = dividerActiveColor dividerColor = dividerActiveColor
} }
/// The animation for the divider when editing ends. /// The animation for the divider when editing ends.
open func dividerEditingDidEndAnimation() { fileprivate func dividerEditingDidEndAnimation() {
dividerThickness = dividerNormalHeight dividerThickness = dividerNormalHeight
dividerColor = dividerNormalColor dividerColor = dividerNormalColor
} }
/// The animation for the placeholder when editing begins. /// The animation for the placeholder when editing begins.
open func placeholderEditingDidBeginAnimation() { fileprivate func placeholderEditingDidBeginAnimation() {
updatePlaceholderLabelColor()
guard isPlaceholderAnimated else { guard isPlaceholderAnimated else {
return return
} }
...@@ -579,7 +635,9 @@ open class TextField: UITextField { ...@@ -579,7 +635,9 @@ open class TextField: UITextField {
} }
/// The animation for the placeholder when editing ends. /// The animation for the placeholder when editing ends.
open func placeholderEditingDidEndAnimation() { fileprivate func placeholderEditingDidEndAnimation() {
updatePlaceholderLabelColor()
guard isPlaceholderAnimated else { guard isPlaceholderAnimated else {
return return
} }
...@@ -597,66 +655,8 @@ open class TextField: UITextField { ...@@ -597,66 +655,8 @@ open class TextField: UITextField {
s.placeholderLabel.transform = CGAffineTransform.identity s.placeholderLabel.transform = CGAffineTransform.identity
s.placeholderLabel.x = s.leftViewWidth s.placeholderLabel.x = s.leftViewWidth
s.placeholderLabel.y = 0 s.placeholderLabel.y = 0
s.placeholderLabel.textColor = s.placeholderNormalColor
}) { [weak self] _ in }) { [weak self] _ in
self?.isAnimating = false self?.isAnimating = false
} }
} }
/// Prepares the divider.
private func prepareDivider() {
dividerColor = dividerNormalColor
}
/// Prepares the placeholderLabel.
private func preparePlaceholderLabel() {
font = RobotoFont.regular(with: 16)
placeholderNormalColor = Color.darkText.others
addSubview(placeholderLabel)
addObserver(self, forKeyPath: "placeholderLabel.text", options: [], context: &TextFieldContext)
}
/// Prepares the detailLabel.
private func prepareDetailLabel() {
detailLabel.font = RobotoFont.regular(with: 12)
detailLabel.numberOfLines = 0
detailColor = Color.darkText.others
addSubview(detailLabel)
addObserver(self, forKeyPath: "detailLabel.text", options: [], context: &TextFieldContext)
}
/// Prepares the leftView.
private func prepareLeftView() {
leftView?.contentMode = .left
}
/// Prepares the target handlers.
private func prepareTargetHandlers() {
addTarget(self, action: #selector(handleEditingDidBegin), for: .editingDidBegin)
addTarget(self, action: #selector(handleEditingChanged), for: .editingChanged)
addTarget(self, action: #selector(handleEditingDidEnd), for: .editingDidEnd)
}
/// Prepares the textAlignment.
private func prepareTextAlignment() {
textAlignment = .rightToLeft == UIApplication.shared.userInterfaceLayoutDirection ? .right : .left
}
/// Updates the placeholderLabel attributedText.
private func updatePlaceholderLabelColor() {
guard let v = placeholder else {
return
}
placeholderLabel.attributedText = NSAttributedString(string: v, attributes: [NSForegroundColorAttributeName: isEditing ? placeholderActiveColor : placeholderNormalColor])
}
/// Updates the detailLabel attributedText.
private func updateDetailLabelColor() {
guard let v = detail else {
return
}
detailLabel.attributedText = NSAttributedString(string: v, attributes: [NSForegroundColorAttributeName: detailColor])
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment