我没有故事板,一切都是程序化的。我有三个TextFields,其中一个是隐藏的(isHidden = true),在登录按钮后面,登录按钮下面是一个注册按钮。如果点击注册按钮,登录按钮会在注册按钮下滑动,然后使用layoutSubViews()显示隐藏的textField,并将设置为隐藏为false。
我的问题是,当点击任何文本字段时,loginButton会移回其原始位置。我已经尝试将textfield委托移动到viewcontroller,调用willLayoutSubviews和didLayoutSubviews中的setup()但仍然会发生同样的事情。
的ViewController:
class WelcomeScreenViewController: UIViewController {
private var currentUser: SplitterUser? {
didSet {
let nextViewController = MyBillsViewController()
nextViewController.currentUser = self.currentUser
present(nextViewController, animated: true)
}
}
// swiftlint:disable line_length
private let titleLogoLabel = TitleLabelLogo(frame: CGRect.zero, accessID: AccesID.titleLogoLabel)
private let emailTextField = SplitterTextField(frame: CGRect.zero, accessID: AccesID.emailTextField)
private let passwordTextField = SplitterTextField(frame: CGRect.zero, accessID: AccesID.passwordTextField)
private let confirmPasswordTextField = SplitterTextField(frame: CGRect.zero, accessID: AccesID.confirmPasswordTextField)
private let loginButton = SplitterButton(frame: CGRect.zero, accessID: AccesID.loginButton)
private let registerButton = SplitterButton(frame: CGRect.zero, accessID: AccesID.registerButton)
// swiftlint:enable line_length
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
private func setup() {
view.backgroundColor = Color.mainBackground
view.addSubview(titleLogoLabel)
view.addSubview(emailTextField)
view.addSubview(passwordTextField)
view.addSubview(confirmPasswordTextField)
view.addSubview(loginButton)
view.addSubview(registerButton)
applyCommonLayoutFeaturesToAllViews()
placeTitleLogoLabel()
placeEmailTextField()
placePasswordTextField()
placePasswordConfirmationTextField()
placeLoginButton()
placeRegisterButton()
setupKeyboard()
}
private func applyCommonLayoutFeaturesToAllViews() {
view.subviews.forEach { subview in
subview.pinToSuperview(edges: [.left, .right])
subview.translatesAutoresizingMaskIntoConstraints = false
}
}
private func placeTitleLogoLabel() {
let titleLogoLabelY = view.frame.height/4.5
titleLogoLabel.pinTop(to: view, constant: titleLogoLabelY)
titleLogoLabel.addHeightConstraint(with: Layout.titleLogoTextHeight)
}
private func placeEmailTextField() {
emailTextField.centerYToSuperview()
emailTextField.addHeightConstraint(with: Layout.textFieldHeight)
}
private func placePasswordTextField() {
passwordTextField.pinTop(to: emailTextField,
constant: Layout.textFieldHeight + Layout.spacer,
priority: .required,
relatedBy: .equal)
passwordTextField.addHeightConstraint(with: Layout.textFieldHeight)
}
private func placePasswordConfirmationTextField() {
confirmPasswordTextField.pinTop(to: passwordTextField,
constant: Layout.textFieldHeight + Layout.spacer,
priority: .required,
relatedBy: .equal)
confirmPasswordTextField.addHeightConstraint(with: Layout.textFieldHeight)
confirmPasswordTextField.isHidden = true
}
private func placeLoginButton() {
loginButton.pinTop(to: passwordTextField,
constant: Layout.textFieldHeight + Layout.spacer,
priority: .required,
relatedBy: .equal)
loginButton.addHeightConstraint(with: Layout.buttonHeight)
loginButton.addTarget(self, action: #selector(loginButtonTapped), for: .touchUpInside)
}
private func placeRegisterButton() {
registerButton.pinTop(to: loginButton,
constant: Layout.buttonHeight + Layout.spacer,
priority: .required,
relatedBy: .equal)
registerButton.addHeightConstraint(with: Layout.buttonHeight)
registerButton.addTarget(self, action: #selector(registerButtonTapped), for: .touchUpInside)
}
@objc private func registerButtonTapped() {
if confirmPasswordTextField.isHidden {
animateLoginButton()
} else {
registerNewUser()
}
}
@objc private func loginButtonTapped() {
if !confirmPasswordTextField.isHidden {
animateLoginButton()
self.view.layoutSubviews()
} else {
//segue to next vc
}
}
private func animateLoginButton() {
if confirmPasswordTextField.isHidden {
moveLoginButtonDown()
} else {
moveLoginButtonUp()
}
}
private func moveLoginButtonDown() {
//Move loginButton down revealing confirmationPasswordTextView behind it
UIView.animate(withDuration: 0.3, animations: {
self.loginButton.frame.origin.y += Layout.loginButtonYMovement
self.confirmPasswordTextField.isHidden = false
})
}
private func moveLoginButtonUp() {
//Move the loginButton up, when it has finished moving hide the confirmationPasswordTextView
UIView.animate(withDuration: 0.3, animations: {
self.loginButton.frame.origin.y -= Layout.loginButtonYMovement
}, completion: { _ in
self.confirmPasswordTextField.isHidden = true
})
}
}
extension UIViewController {
func setupKeyboard() {
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillShow(sender:)),
name: NSNotification.Name.UIKeyboardWillShow,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillHide(sender:)),
name: NSNotification.Name.UIKeyboardWillHide,
object: nil)
}
@objc private func keyboardWillShow(sender: NSNotification) {
self.view.frame.origin.y = Layout.welcomeScreenKeyboardMovement
}
@objc private func keyboardWillHide(sender: NSNotification) {
self.view.frame.origin.y = 0
}
}
的TextField:
class SplitterTextField: UITextField, UITextFieldDelegate {
var accessID: String!
required init(frame: CGRect, accessID: String) {
super.init(frame: frame)
self.accessID = accessID
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
private func setup() {
delegate = self
backgroundColor = Color.textFieldBackground
accessibilityIdentifier = accessID
textAlignment = .center
returnKeyType = .done
placeholder = NSLocalizedString("\(accessID!)PlaceHolder", comment: "")
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
resignFirstResponder()
return true
}
}
我迷失了还有什么可尝试的。任何想法都会很棒。感谢
答案 0 :(得分:0)
像往常一样添加您键入WelcomeScreenViewController
的XIB文件(因此没有故事板)。以图形方式创建自动布局约束(这更容易)。
将一些约束作为视图控制器代码中的插件,然后根据需要设置动画(以及某些子视图的alpha
)。
我知道这是一个完全不同的解决方案,但我认为你做的事情太复杂了。 UIViewController
/ XIB对仍然是构建UI的一种非常好用且简单的方法。
答案 1 :(得分:0)
您已对视图设置约束以将其排除。自动布局使用约束来计算视图的帧。然后直接修改loginButton
的框架:
self.loginButton.frame.origin.y += Layout.loginButtonYMovement
下次自动布局运行时,它会根据约束重置loginButton
的帧。
要移动loginButton
,您需要修改设置其框架的约束。因此,例如,您应该(在实例变量中)保存您在placeLoginButton
中创建的顶部约束。然后在moveLoginButtonDown
中,您可以修改已保存约束的常量,并在动画块中调用self.view.layoutSubviews()
。