Skip to content

Commit

Permalink
This CL adds the ability to inject a custom UITextField/M3CInsetTextF…
Browse files Browse the repository at this point in the history
…ield subclass into M3CTextField. This makes it so that integrators are not restricted by the fact that M3CTextField wraps UITextField instead of inheriting from it (unlike MDCTextField). It allows integrators to still use any of the modifications they did by subclassing MDCTextField, while being able to benefit from M3CTextField.

One use-case/blocker we faced on our team was the inability to control cut/copy/paste behavior. This requires subclassing UITextField and overriding `canPerformAction`.

PiperOrigin-RevId: 584138917
  • Loading branch information
Nobody authored and material-automation committed Nov 20, 2023
1 parent ce2ef97 commit 9550d68
Showing 1 changed file with 30 additions and 18 deletions.
48 changes: 30 additions & 18 deletions components/M3CTextField/src/M3CTextField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,7 @@ public final class M3CTextField: UIView, M3CTextInput {
private var trailingLabelColors: [UIControl.State: UIColor] = [:]
private var tintColors: [UIControl.State: UIColor] = [:]

@objc public lazy var textContainer: UITextField = {
let textField = M3CInsetTextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.adjustsFontForContentSizeCategory = true
textField.font = defaultTextContainerFont
textField.layer.borderWidth = 1.0
textField.layer.cornerRadius = 10.0

// When firstResponder status changes, apply all colors associated with the resulting
// UIControlState.
textField.firstResponderChangeHandler = { [weak self] in
self?.applyAllColors()
}

return textField
}()
@objc public var textContainer: UITextField

/// Proxy property for the underlying text field's `delegate` property.
@objc public var delegate: UITextFieldDelegate? {
Expand Down Expand Up @@ -148,9 +133,20 @@ public final class M3CTextField: UIView, M3CTextInput {
@objc public lazy var trailingLabel: UILabel = buildLabel()

/// Initializes a `M3CTextField` with a supporting label, title label, and trailing label.
public init() {
super.init(frame: .zero)
@objc public convenience init() {
self.init(textContainer: M3CInsetTextField())
}

/// Initializes a `M3CTextField` with a supporting label, title label, and trailing label.
///
/// @param textContainer Custom `textContainer` subclass to use as the underlying text
/// field in order to provide more customization. Overriding the default text container
/// may lead to unexpected behavior. There are no guarantees when overriding members of the
/// subclass and this should be used very sparingly.
@objc public required init(textContainer: UITextField) {
self.textContainer = textContainer
super.init(frame: .zero)
configure(textContainer)
configureStackViews()
}

Expand Down Expand Up @@ -208,6 +204,22 @@ public final class M3CTextField: UIView, M3CTextInput {
// leading label when M3CTextField is placed inside of a UICollectionViewCell.
trailingLabel.isHidden = (trailingLabel.text ?? "").isEmpty
}

private func configure(_ textField: UITextField) {
textField.translatesAutoresizingMaskIntoConstraints = false
textField.adjustsFontForContentSizeCategory = true
textField.font = defaultTextContainerFont
textField.layer.borderWidth = 1.0
textField.layer.cornerRadius = 10.0

if let insetTextField = textField as? M3CInsetTextField {
// When firstResponder status changes, apply all colors associated with the resulting
// UIControlState.
insetTextField.firstResponderChangeHandler = { [weak self] in
self?.applyAllColors()
}
}
}
}

// MARK: M3CTextField Custom Clear Button
Expand Down

0 comments on commit 9550d68

Please sign in to comment.