Custom TextField does not comply to constraints

Viewed 326

I've been having this issue with HoshiTextField for quite some time now, I also opened an issue on git but didn't get an answer...

This is how it should look like and how it looks like if the user is selecting the textField:

enter image description here

The problem occurs when setting the textField to becomeFirstResponder inside viewDidLoad or when popping a ViewController while the textField inside the first VC was selected. Apparently that messes up the frames or constraints of the textField but I have absolutely no idea how to fix this.

enter image description here

As you can see the "Email-Adesse"-text is moving to the upper left and when pushing and poping back to the ViewController it moves even further outside the constraints. When checking the View Hirarchy with the debugger the "Email-Adresse"-Text looks perfectly in place even though it isn't. Setting up the constraints inside viewDidAppear didn't change anything.

I constrain the textFields like every other element:

let emailTextField: HoshiTextField = {
    let v = HoshiTextField()
    v.borderActiveColor = .white
    v.borderInactiveColor = .white
    v.textColor = .white
    v.font = UIFont(name: "AvenirNext-Regular", size: 17)
    v.placeholder = "Email-Adresse"
    v.placeholderColor = .white
    v.placeholderFontScale = 0.8
    v.minimumFontSize = 13
    v.borderStyle = .line
    v.autocapitalizationType = .none
    v.translatesAutoresizingMaskIntoConstraints = false
    return v
}()
emailTextField.topAnchor.constraint(equalTo: theLabel.bottomAnchor, constant: 20).isActive = true
    emailTextField.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 30).isActive = true
    emailTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
    emailTextField.heightAnchor.constraint(equalToConstant: 60).isActive = true

If anyone can help me out here I would be so grateful! I hope the problem is clear, you can also look at my project to see the problem yourself:

Git repo to my project

2 Answers

Here is full test controller with 2 alternates of possible solution

Demo: Alternate 1 - often appears already expanded

demo

Demo: Alternate 2 - always there is a delay, expanding is visible

demo2

class ViewController2: UIViewController {
    @IBOutlet weak var theLabel: UILabel!
    private weak var emailTextField: HoshiTextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        emailTextField = {
            let v = HoshiTextField()
            v.borderActiveColor = .white
            v.borderInactiveColor = .white
            v.textColor = .white
            v.font = UIFont(name: "AvenirNext-Regular", size: 17)
            v.placeholder = "Email-Adresse"
            v.placeholderColor = .white
            v.placeholderFontScale = 0.8
            v.minimumFontSize = 13
            v.borderStyle = .line
            v.autocapitalizationType = .none
            v.translatesAutoresizingMaskIntoConstraints = false
            return v
        }()
        self.view.addSubview(emailTextField)
        emailTextField.topAnchor.constraint(equalTo: theLabel.bottomAnchor, constant: 20).isActive = true
            emailTextField.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 30).isActive = true
            emailTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
            emailTextField.heightAnchor.constraint(equalToConstant: 60).isActive = true

//        DispatchQueue.main.async {
//            self.emailTextField.becomeFirstResponder()    // Alternate 1
//        }
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        emailTextField.becomeFirstResponder()          // Alternate 2
    }
}

Sorry I misunderstood your question at first.

I feel like the issue is that at some point as the HoshiTextField is selected and leaves the screen, it becomes deselected, but it does not update it's layout. So then when you come back the animations still stay relatively the same, but from a different angle.

I'm not sure how to solve that problem precisely, but I was able to get the screen to look normal after adding the following to your EmailVC

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    view.endEditing(true)
}

I hope that that's fine. It's not really solving the issue, but it does get the UI of your app looking proper in this scenario.

Related