Raymond
Raymond

Reputation: 1258

UITextField custom clear button jumps on layoutIfNeeded

gif

I've a custom clear button for text field. This button jumps from left to right if I use layoutIfNeeded in keyboard show function. It happens only first time I edit text field, doesn't happen on subsequent edit. How do I fix it? I need layoutIfNeeded for smooth animation.

class MyViewController: UIViewController {
    @IBOutlet weak var emailField: CustomTextField!

    @objc func handleKeyboardNotification(_ notification: Notification) {

        // calculate height etc....

        UIView.animate(withDuration: 0.5, animations: { () -> Void in
            self.view.layoutIfNeeded() // This causes clear button to jump
        })

    }
}

class CustomTextField: UITextField {

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        self.initialize()

        self.translatesAutoresizingMaskIntoConstraints = false

        // other code
    }

    func initialize() {
        self.text = ""
        self.setPlaceHolderTextFontAndColour(text: self.placeholder!, font: UIFont.body, colour: .lightGray)

        let clearButton = UIButton(frame: CGRect(x: 0, y: 0, width: 32, height: 32))
        clearButton.setImage(UIImage.clearButton, for: [])

        self.rightView = clearButton
        clearButton.addTarget(self, action: #selector(self.clearClicked(sender: )), for: .touchUpInside)

        self.clearButtonMode = .never
        self.rightViewMode = .whileEditing
    }
}

Upvotes: 1

Views: 611

Answers (2)

Alex
Alex

Reputation: 2160

Also try in your CustomTextField class (if you don't need other animations there)

override func layoutSubviews() {
    UIView.performWithoutAnimation {
        super.layoutSubviews()
    }
}

Upvotes: 2

DonMag
DonMag

Reputation: 77486

This looks like something I'd call an actual bug. Of course, I could be wrong...

One way that could fix it:

In your custom text field's initialize() code, set self.rightViewMode = .always, then add this:

override func layoutSubviews() {
    super.layoutSubviews()
    if self.rightViewMode == .always {
        self.rightViewMode = .whileEditing
    }
}

I've only done quick testing, but it seems to do the job.

Side note: any view you add in Storyboard is automatically loaded with translatesAutoresizingMaskIntoConstraints set to false, so you do not need to do that in your awakeFromNib() func.

Upvotes: 2

Related Questions