2017-08-02 116 views
1

我沒有任何故事板,所有內容都是編程式的。我有三個TextField,其中一個隱藏(isHidden = true),在登錄按鈕後面,登錄按鈕下面是一個註冊按鈕。如果點擊註冊按鈕,登錄按鈕在註冊按鈕下滑動,隱藏的textField顯示使用layoutSubViews()並將設置爲隱藏爲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 
    } 
} 

文本字段:

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

當按下登錄按鈕的位置正在重新設置然後動畫喲umean? –

+0

沒有按下登錄按鈕和註冊按鈕,因爲他們應該做,但當我點擊一個文本字段後,登錄按鈕已移動它重置回到它的起點 – Wazza

+0

是否有代碼textFieldShouldReturn以外代碼中的文本字段的任何edlegate函數? –

回答

0

添加一個XIB文件(所以沒有故事板),你像往常一樣鍵入WelcomeScreenViewController。以圖形方式創建自動佈局約束(這非常容易)。

有一些限制作爲視圖控制器代碼中的插座,然後生成動畫(根據需要連同某些子視圖的alpha)。

我知道這是一個完全不同的解決方案,但我認爲你讓事情太複雜。 UIViewController/XIB對仍然是構建UI的一個非常好的和簡單的方法。

+0

任務(我已經設置爲自己)的全部要點是不使用它們,因爲我工作的公司不使用任何圖形界面。謝謝 – Wazza

+0

我明白了。他們爲什麼不呢? –

+0

有幾個原因,我能記得的是,當多個人在一個有故事板等的項目上工作時,github會使問題變得複雜,並且使得解決問題變得更加難以發現,因爲您必須通過IB來搜索。我認爲 – Wazza

0

你已經對你的視圖設置了約束條件來展開它們。自動佈局使用約束來計算視圖的幀。然後你修改的loginButton直接框架:

self.loginButton.frame.origin.y += Layout.loginButtonYMovement 

下一次自動佈局運行時,它重置的loginButton基於約束的框架。

要移動loginButton,您需要修改設置其框架的約束。因此,例如,您應該保存(在實例變量中)在placeLoginButton中創建的頂端約束。然後在moveLoginButtonDown中,您可以修改保存的約束的常量,並在動畫塊中調用self.view.layoutSubviews()

+0

我不太明白如何實現你的說法,你介意給我一點幫助嗎? – Wazza