点击文本字段后重置位置的动画视图

时间:2017-08-02 14:48:16

标签: ios swift xcode

我没有故事板,一切都是程序化的。我有三个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
    }
}

我迷失了还有什么可尝试的。任何想法都会很棒。感谢

2 个答案:

答案 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()

相关问题