我使用Swift与iOS编程,我使用这段代码来移动UITextField,但它不起作用。我正确地调用了函数keyboardWillShow,但是文本字段没有移动。我正在使用自动布局。
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self);
}
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
//let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
var frame = self.ChatField.frame
frame.origin.y = frame.origin.y - keyboardSize.height + 167
self.chatField.frame = frame
println("asdasd")
}
}
如果你正在使用自动布局,我假设你已经设置了底部空间为Superview约束。如果是这种情况,您只需更新约束的值。这是你如何用一点动画来做到这一点。
func keyboardWasShown(notification: NSNotification) {
let info = notification.userInfo!
let keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
UIView.animateWithDuration(0.1, animations: { () -> Void in
self.bottomConstraint.constant = keyboardFrame.size.height + 20
})
}
添加硬编码的20只是为了将文本框弹出到键盘上方一点。否则键盘的上边距和文本框的下边距将会接触。
当键盘关闭时,将约束的值重置为原始值。
我创建了一个Swift 3协议来处理键盘的出现/消失
import UIKit
protocol KeyboardHandler: class {
var bottomConstraint: NSLayoutConstraint! { get set }
func keyboardWillShow(_ notification: Notification)
func keyboardWillHide(_ notification: Notification)
func startObservingKeyboardChanges()
func stopObservingKeyboardChanges()
}
extension KeyboardHandler where Self: UIViewController {
func startObservingKeyboardChanges() {
// NotificationCenter observers
NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillShow, object: nil, queue: nil) { [weak self] notification in
self?.keyboardWillShow(notification)
}
// Deal with rotations
NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil, queue: nil) { [weak self] notification in
self?.keyboardWillShow(notification)
}
// Deal with keyboard change (emoji, numerical, etc.)
NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextInputCurrentInputModeDidChange, object: nil, queue: nil) { [weak self] notification in
self?.keyboardWillShow(notification)
}
NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillHide, object: nil, queue: nil) { [weak self] notification in
self?.keyboardWillHide(notification)
}
}
func keyboardWillShow(_ notification: Notification) {
let verticalPadding: CGFloat = 20 // Padding between the bottom of the view and the top of the keyboard
guard let value = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
let keyboardHeight = value.cgRectValue.height
// Here you could have more complex rules, like checking if the textField currently selected is actually covered by the keyboard, but that's out of this scope.
self.bottomConstraint.constant = keyboardHeight + verticalPadding
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.layoutIfNeeded()
})
}
func keyboardWillHide(_ notification: Notification) {
self.bottomConstraint.constant = 0
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.layoutIfNeeded()
})
}
func stopObservingKeyboardChanges() {
NotificationCenter.default.removeObserver(self)
}
}
然后,要在UIViewController中实现它,执行以下操作:
let the viewController conform to this protocol :
class FormMailVC: UIViewControlle, KeyboardHandler {
start observing keyboard changes in viewWillAppear:
// MARK: - View controller life cycle
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
startObservingKeyboardChanges()
}
stop observing keyboard changes in viewWillDisappear:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
stopObservingKeyboardChanges()
}
create an IBOutlet for the bottom constraint from the storyboard:
// NSLayoutConstraints
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
(I recommend having all of your UI embedded inside a "contentView", and linking to this property the bottom constraint from this contentView to the bottom layout guide)
change the constraint priority of the top constraint to 250 (low)
这是为了让整个内容视图在键盘出现时向上滑动。
优先级必须低于子视图中的任何其他约束优先级,包括内容拥抱优先级/内容抗压缩优先级。
确保你的自动布局有足够的约束来决定contentView应该如何滑动。
你可能需要添加一个“大于等于”的约束:
给你!
以下是我对Swift 2.2的解决方案:
首先注册键盘显示/隐藏通知
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(MessageThreadVC.keyboardWillShow(_:)),
name: UIKeyboardWillShowNotification,
object: nil)
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(MessageThreadVC.keyboardWillHide(_:)),
name: UIKeyboardWillHideNotification,
object: nil)
然后在与这些通知相对应的方法中,向上或向下移动主视图
func keyboardWillShow(sender: NSNotification) {
if let keyboardSize = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.frame.origin.y = -keyboardSize.height
}
}
func keyboardWillHide(sender: NSNotification) {
self.view.frame.origin.y = 0
}
诀窍在于“keyboardWillShow”部分,每次“QuickType建议栏”被展开或折叠时,该部分都会被调用。然后我们总是设置主视图的y坐标等于键盘总高度的负值(包括或不包括“QuickType栏”部分)。
最后不要忘记删除观察者
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
我的做法如下:
class SignInController: UIViewController , UITextFieldDelegate {
@IBOutlet weak var scrollView: UIScrollView!
// outlet declartion
@IBOutlet weak var signInTextView: UITextField!
var kbHeight: CGFloat!
/**
*
* @method viewDidLoad
*
*/
override func viewDidLoad() {
super.viewDidLoad()
self.signInTextView.delegate = self
}// end viewDidLoad
/**
*
* @method viewWillAppear
*
*/
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)
}// end viewWillAppear
/**
*
* @method viewDidAppear
*
*/
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
}// end viewDidAppear
/**
*
* @method viewWillDisappear
*
*/
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
/**
*
* @method textFieldShouldReturn
* retun the keyboard value
*
*/
// MARK -
func textFieldShouldReturn(textField: UITextField) -> Bool {
signInTextView.resignFirstResponder()
return true;
}// end textFieldShouldReturn
// MARK - keyboardWillShow
func keyboardWillShow(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
kbHeight = keyboardSize.height
self.animateTextField(true)
}
}
}// end keyboardWillShow
// MARK - keyboardWillHide
func keyboardWillHide(notification: NSNotification) {
self.animateTextField(false)
}// end keyboardWillHide
// MARK - animateTextField
func animateTextField(up: Bool) {
var movement = (up ? -kbHeight : kbHeight)
UIView.animateWithDuration(0.3, animations: {
self.view.frame = CGRectOffset(self.view.frame, 0, movement)
})
}// end animateTextField
/**
*
* @method didReceiveMemoryWarning
*
*/
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}// end didReceiveMemoryWarning
}// end SignInController