UITextField自定义清除按钮在layoutIfNeeded上跳转

UITextField custom clear button jumps on layoutIfNeeded

我有一个用于文本字段的自定义清除按钮。如果我在键盘显示功能中使用layoutIfNeeded,这个按钮会从左跳到右。它只在我第一次编辑文本字段时发生,在后续编辑中不会发生。我如何解决它?我需要 layoutIfNeeded 才能使动画流畅。

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
    }
}

这看起来像是我称之为实际错误的东西。当然,我可能是错的...

一种解决方法:

在自定义文本字段的 initialize() 代码中,设置 self.rightViewMode = .always,然后添加:

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

我只做了快速测试,但它似乎可以完成工作。

旁注:您在情节提要中添加的任何视图都会自动加载 translatesAutoresizingMaskIntoConstraints 设置为 false,因此您无需在 awakeFromNib() 函数中执行此操作。

也试试你的 CustomTextField class(如果你不需要其他动画)

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