我试图通过在约束的常量中添加/减去键盘的高度来显示和隐藏键盘时更新按钮的约束。
我之前有过这个工作,但经过一些重新考虑后,它已经停止工作了。以前,keyboardWillShow:
和keyboardWillHide:
的实现完全如下所示。我曾尝试使用setNeedsUpdateConstraints
和setNeedsLayout
尝试强制刷新,但无济于事。
在进行一些简单的print()
调试时,buttonHorizontalConstraint.constant
确实会更新,但这些更改并未直观反映。
class RegistrationNameView: UIView {
let questionLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFontOfSize(21.0)
label.text = "Hey, what's your name?"
label.textAlignment = .Center
label.textColor = UIColor.lightGrayColor()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let nameField: UITextField = {
let field = UITextField()
field.autocorrectionType = .No
field.font = UIFont.boldSystemFontOfSize(28.0)
field.placeholder = "Full name"
field.returnKeyType = .Next
field.textAlignment = .Center
field.translatesAutoresizingMaskIntoConstraints = false
return field
}()
let nextButton: UIButton = {
let button = UIButton()
button.setTitle("Continue", forState: .Normal)
button.setTitleColor(UIColor.whiteColor(), forState: .Normal)
button.titleLabel?.font = UIFont.boldSystemFontOfSize(17.0)
button.backgroundColor = UIColor(red: 0.263, green: 0.910, blue: 0.847, alpha: 1)
button.layer.cornerRadius = Global.UISizes.CornerRadius
button.translatesAutoresizingMaskIntoConstraints = false
button.contentEdgeInsets = UIEdgeInsetsMake(16.0, 0, 16.0, 0)
return button
}()
var buttonHorizontalConstraint = NSLayoutConstraint()
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.whiteColor()
// Add subviews
self.addSubview(questionLabel)
self.addSubview(nameField)
self.addSubview(nextButton)
nameField.becomeFirstResponder()
// Constraint helpers
let spacer = Global.UISizes.SpacingUnit
let margins = self.layoutMarginsGuide
let layoutConstraints: [NSLayoutConstraint] = {
var constraints = [NSLayoutConstraint]()
// Title Label Constraints
constraints.append(
questionLabel.bottomAnchor.constraintEqualToAnchor(nameField.topAnchor, constant: -(spacer * 2)))
constraints.append(questionLabel.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor))
constraints.append(questionLabel.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor))
// Description Label Constraints
constraints.append(nameField.topAnchor.constraintEqualToAnchor(margins.centerYAnchor, constant: spacer * -12))
constraints.append(nameField.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor))
constraints.append(nameField.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor))
// Sign Up Button Constraints
self.buttonHorizontalConstraint = nextButton.bottomAnchor.constraintEqualToAnchor(margins.bottomAnchor, constant: -(spacer * 2))
constraints.append(self.buttonHorizontalConstraint)
constraints.append(nextButton.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor))
constraints.append(nextButton.trailingAnchor.constraintEqualToAnchor(margins.trailingAnchor))
return constraints
}()
NSLayoutConstraint.activateConstraints(layoutConstraints)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo! as NSDictionary).objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue.size {
self.buttonHorizontalConstraint.constant -= keyboardSize.height
}
}
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo! as NSDictionary).objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue.size {
self.buttonHorizontalConstraint.constant += keyboardSize.height
}
}
}
class RegistrationNameViewController: UIViewController {
var nameView: RegistrationNameView! { return self.view as! RegistrationNameView }
override func viewDidLoad() {
super.viewDidLoad()
let nameView = RegistrationNameView(frame: CGRectZero)
nameView.nextButton.addTarget(self, action: "nextStep:", forControlEvents: .TouchUpInside)
self.view = nameView
}
func nextStep(sender: AnyObject) {
print("going to the next step \(sender)")
let credentialsViewController = RegistrationCredentialsViewController()
self.navigationController?.pushViewController(credentialsViewController, animated: true)
}
}
class RegistrationNavigationController: UINavigationController, UINavigationControllerDelegate {
var nameViewController: RegistrationNameViewController = RegistrationNameViewController()
var credViewController: RegistrationCredentialsViewController = RegistrationCredentialsViewController()
override init(rootViewController: UIViewController) {
super.init(rootViewController: rootViewController)
self.delegate = self
}
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
let type = String(viewController.dynamicType)
switch type {
case "RegistrationNameViewController":
// Add keyboard notifications to RegistrationNameViewController
NSNotificationCenter.defaultCenter().addObserver(nameViewController.view,
selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(nameViewController.view,
selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
case "RegistrationCredentialsViewController":
// Remove keyboard notifications to RegistrationNameViewController before
// registering for new notifications
NSNotificationCenter.defaultCenter().removeObserver(nameViewController.view)
// Add keyboard notifications to RegistrationCredentialsViewController
NSNotificationCenter.defaultCenter().addObserver(credViewController.view,
selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(credViewController.view,
selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
default:
print("Default")
}
}
}
感谢您的帮助!
答案 0 :(得分:0)
经过一番挖掘后,我自己解决了这个问题。
我认为问题在于NSNotificationCenter
观察者注册是在后台线程上发生的,这导致实际影响UI的方法实际上没有改变UI。
我没有在navigationController:willShowViewController:animated:
中注册观察者,而是在viewWillAppear
中注册观察者,并在viewWillDisappear
中取消注册。这种情况发生在RegistrationNameViewController
而不是RegistrationNavigationController
。
override func viewWillAppear(animated:
NSNotificationCenter.defaultCenter().addObserver(self.view,
selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self.view,
selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
(self.view as! RegistrationNameView).nameField.becomeFirstResponder()
}
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self.view)
}
这使得navigationController:willShowViewController:animated:
不再需要,可以从RegistrationNavigationController.swift