1

I am trying to make my own google material textfield in ios. Where the underline changes colour when tapped and the placeholder text moves up when the user starts to fill in the textfield. Like this:

enter image description here

I started by following this feed here.

So far I have the line underneath the text working, so when the user taps the line changes colour and when the user taps outside the textfield the line changes back to original colour.

I now need to work out how to make the placeholder text stay on screen and animate up, is this even possible? I don't think it is so my next thought was to add a UILabel to my custom textField class and animate that up but I cant work out how to do this? Is this even possible?

Custom textfield class:

class CustomTextField: UITextField, UITextFieldDelegate{

    let border = CALayer()

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        delegate = self
        createBorder()
    }
    required override init(frame: CGRect) {
        super.init(frame: frame)
        delegate = self
        createBorder()
    }

    func createBorder(){
        let width = CGFloat(2.0)
        border.borderColor = UIColor(red:0.60, green:0.60, blue:0.60, alpha:1.0).cgColor
        border.frame = CGRect(x: 0, y: self.frame.size.height-width, width: self.frame.size.width, height: self.frame.size.height)
        border.borderWidth = width
        self.layer.addSublayer(border)
        self.layer.masksToBounds = true
    }

    func textFieldDidBeginEditing(_ textField: UITextField) {
        clearButtonMode = .whileEditing
        movePlaceholderUp()
    }
    func textFieldDidEndEditing(_ textField: UITextField) {
        movePlaceholderDown()
    }

    func movePlaceholderUp(){
        border.borderColor = UIColor(red:0.87, green:0.30, blue:0.32, alpha:1.0).cgColor        
    }
    func movePlaceholderDown(){
        border.borderColor = UIColor(red:0.60, green:0.60, blue:0.60, alpha:1.0).cgColor
    }
}
spoax
  • 471
  • 9
  • 29

1 Answers1

7

Correct me if my understanding is wrong but you want to animate your placeholder text of UITextField when you start typing right? If so, then I think you are on the right track about adding a label inside UITextField and animating that when you start typing.

I did something similar (I animate the label only if user types something inside the textfield), but your requirement is easier.

class View: UIView {

  private var usernameLabelYAnchorConstraint: NSLayoutConstraint!
  private var usernameLabelLeadingAnchor: NSLayoutConstraint!

  private lazy var usernameLBL: UILabel! = {
    let label = UILabel()
    label.text = "Username"
    label.translatesAutoresizingMaskIntoConstraints = false
    label.alpha = 0.5
    return label
  }()

  private lazy var usernameTextField: UITextField! = {
    let textLabel = UITextField()
    textLabel.borderStyle = .roundedRect
    textLabel.translatesAutoresizingMaskIntoConstraints = false
    return textLabel
  }()

  init() {
    super.init(frame: UIScreen.main.bounds)
    addSubview(usernameTextField)
    addSubview(usernameLBL)
    backgroundColor = UIColor(white: 1, alpha: 1)
    usernameTextField.delegate = self

    configureViews()
  }

  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  func configureViews() {
    let margins = self.layoutMarginsGuide
    usernameLabelYAnchorConstraint = usernameLBL.centerYAnchor.constraint(equalTo: usernameTextField.centerYAnchor, constant: 0)
    usernameLabelLeadingAnchor = usernameLBL.leadingAnchor.constraint(equalTo: usernameTextField.leadingAnchor, constant: 5)

    NSLayoutConstraint.activate([
      usernameTextField.centerXAnchor.constraint(equalTo: margins.centerXAnchor),
      usernameTextField.centerYAnchor.constraint(equalTo: margins.centerYAnchor),
      usernameTextField.widthAnchor.constraint(equalToConstant: 100),
      usernameTextField.heightAnchor.constraint(equalToConstant: 25),

      usernameLabelYAnchorConstraint,
      usernameLabelLeadingAnchor,
      ])
  }

}

extension View: UITextFieldDelegate {

  func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    return textField.resignFirstResponder()
  }

  func textFieldDidBeginEditing(_ textField: UITextField) {
    usernameLabelYAnchorConstraint.constant = -25
    usernameLabelLeadingAnchor.constant = 0
    performAnimation(transform: CGAffineTransform(scaleX: 0.8, y: 0.8))
  }

  func textFieldDidEndEditing(_ textField: UITextField) {
    if let text = textField.text, text.isEmpty {
      usernameLabelYAnchorConstraint.constant = 0
      usernameLabelLeadingAnchor.constant = 5
      performAnimation(transform: CGAffineTransform(scaleX: 1, y: 1))
    }
  }

  fileprivate func performAnimation(transform: CGAffineTransform) {
    UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
      self.usernameLBL.transform = transform
      self.layoutIfNeeded()
    }, completion: nil)
  }

}

Demo

Unheilig
  • 16,196
  • 193
  • 68
  • 98
superrehtard
  • 118
  • 1
  • 8