点击文本字段后动画视图重置位置
Posted
技术标签:
【中文标题】点击文本字段后动画视图重置位置【英文标题】:Animated views resetting position after tapping textfield 【发布时间】:2017-08-02 14:48:15 【问题描述】:我没有故事板,一切都是程序化的。我有三个 TextField,其中一个是隐藏的(isHidden = true),在登录按钮后面,登录按钮下方是一个注册按钮。如果您点击注册按钮,登录按钮会滑到注册按钮下方,然后使用 layoutSubViews() 显示隐藏的 textField 并将 isHidden 设置为 false。
我的问题是,当点击任何文本字段时,loginButton 会移回其原始位置。我尝试将文本字段委托移动到视图控制器,在 willLayoutSubviews 和 didLayoutSubviews 中调用 setup(),但同样的事情仍然发生。
视图控制器:
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
我不知道还有什么可以尝试的。任何想法都会很棒。谢谢
【问题讨论】:
当按下登录按钮时,位置正在重置,然后动画你是什么意思? 没有按登录按钮和注册按钮,但当我在登录按钮移动后点击文本字段时,它会重置回起点 除了 textFieldShouldReturn 之外,您的代码中是否有任何文本字段的 edlegate 函数? 不,这是唯一的功能 你在layoutSubviews中有位置设置吗? 【参考方案1】:添加一个您像往常一样键入WelcomeScreenViewController
的XIB 文件(因此没有故事板)。以图形方式创建自动布局约束(这更容易)。
在您的视图控制器代码中有一些这样的约束作为出口,然后您可以对其进行动画处理(根据需要与一些子视图的 alpha
一起)。
我知道这是一个完全不同的解决方案,但我认为你把事情弄得太复杂了。 UIViewController
/XIB 对仍然是构建 UI 的一种非常好且简单的方法。
【讨论】:
任务的重点(我已经为自己设定)是不要使用它们,因为我工作的公司不使用任何图形界面。不过谢谢 我明白了。他们为什么不呢? 几个原因,我记得的一个原因是,当多个人在一个项目上工作时,有故事板等会使 github 变得复杂,并且由于您必须通过 IB 搜索而使解决问题变得更加困难。我认为 这确实是不使用 Storyboard 的一个很好的理由。由于这个原因和其他原因,我讨厌 Storyboard。但是他们为什么不为每个屏幕使用代码/XIB 对并自定义UIView
?当您与多人在一起时,这一切都很好。
我不确定,因为我没有问。当我这样做时,我会告诉你,我可能是错的,他们确实这样做了,但我认为他们没有。【参考方案2】:
您已经对视图设置了约束以进行布局。自动布局使用约束来计算视图的框架。那你直接修改loginButton
的框架:
self.loginButton.frame.origin.y += Layout.loginButtonYMovement
下次自动布局运行时,它会根据约束重置loginButton
的框架。
要移动loginButton
,您需要修改设置其框架的约束。因此,例如,您应该保存(在实例变量中)您在placeLoginButton
中创建的顶部约束。然后在moveLoginButtonDown
中可以修改保存的约束常量,在动画块中调用self.view.layoutSubviews()
。
【讨论】:
我不太明白如何实现你所说的,你介意给我一点帮助吗?以上是关于点击文本字段后动画视图重置位置的主要内容,如果未能解决你的问题,请参考以下文章