我使用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")
}
}
func registerForKeyboardNotifications(){
//Keyboard
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWasShown), name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillBeHidden), name: UIKeyboardDidHideNotification, object: nil)
}
func deregisterFromKeyboardNotifications(){
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWasShown(notification: NSNotification){
let userInfo: NSDictionary = notification.userInfo!
let keyboardInfoFrame = userInfo.objectForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue()
let windowFrame:CGRect = (UIApplication.sharedApplication().keyWindow!.convertRect(self.view.frame, fromView:self.view))
let keyboardFrame = CGRectIntersection(windowFrame, keyboardInfoFrame!)
let coveredFrame = UIApplication.sharedApplication().keyWindow!.convertRect(keyboardFrame, toView:self.view)
let contentInsets = UIEdgeInsetsMake(0, 0, (coveredFrame.size.height), 0.0)
self.scrollViewInAddCase .contentInset = contentInsets;
self.scrollViewInAddCase.scrollIndicatorInsets = contentInsets;
self.scrollViewInAddCase.contentSize = CGSizeMake((self.scrollViewInAddCase.contentSize.width), (self.scrollViewInAddCase.contentSize.height))
}
/**
this method will fire when keyboard was hidden
- parameter notification: contains keyboard details
*/
func keyboardWillBeHidden (notification: NSNotification) {
self.scrollViewInAddCase.contentInset = UIEdgeInsetsZero
self.scrollViewInAddCase.scrollIndicatorInsets = UIEdgeInsetsZero
}
编辑:我推荐一个更简单、更干净的解决方案。只需将底部间距约束的类更改为KeyboardLayoutConstraint。它会自动展开到键盘高度。
这是一个改进版的@JosephLord的回答。
在iOS 8.3 iPad模拟器上测试,Portrait。Xcode6.3 beta4,我发现他的答案不工作时,键盘隐藏,因为UIKeyboardFrameEndUserInfoKey是“NSRect:{{0, 1024},{768, 264}}”;高度不为0。
这回到使用传统的UIKeyboardWillShowNotification和UIKeyboardWillHideNotification来更好地判断键盘何时隐藏,而不是依赖于结束帧的高度。UIKeyboardWillShowNotification也会在键盘帧改变时发送,所以它应该覆盖所有的用例。
// You have to set this up in storyboard first!.
// It's a vertical spacing constraint between view and bottom of superview.
@IBOutlet weak var bottomSpacingConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardNotification:"), name:UIKeyboardWillShowNotification, object: nil);
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardNotification:"), name:UIKeyboardWillHideNotification, object: nil);
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func keyboardNotification(notification: NSNotification) {
let isShowing = notification.name == UIKeyboardWillShowNotification
if let userInfo = notification.userInfo {
let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
let endFrameHeight = endFrame?.size.height ?? 0.0
let duration:NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.unsignedLongValue ?? UIViewAnimationOptions.CurveEaseInOut.rawValue
let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
self.bottomSpacingConstraint?.constant = isShowing ? endFrameHeight : 0.0
UIView.animateWithDuration(duration,
delay: NSTimeInterval(0),
options: animationCurve,
animations: { self.view.layoutIfNeeded() },
completion: nil)
}
}
我已采取以下方式:
当textfield superview为view时,这很有用
class AdminLoginViewController: UIViewController,
UITextFieldDelegate{
@IBOutlet weak var txtUserName: UITextField!
@IBOutlet weak var txtUserPassword: UITextField!
@IBOutlet weak var btnAdminLogin: UIButton!
private var activeField : UIView?
var param:String!
var adminUser : Admin? = nil
var kbHeight: CGFloat!
override func viewDidLoad()
{
self.addKeyBoardObserver()
self.addGestureForHideKeyBoard()
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func addGestureForHideKeyBoard()
{
let tapGesture = UITapGestureRecognizer(target: self, action: Selector("hideKeyboard"))
tapGesture.cancelsTouchesInView = false
view.addGestureRecognizer(tapGesture)
}
func hideKeyboard() {
self.view.endEditing(true)
}
func addKeyBoardObserver(){
NSNotificationCenter.defaultCenter().addObserver(self, selector: "willChangeKeyboardFrame:",
name:UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "willChangeKeyboardFrame:",
name:UIKeyboardWillHideNotification, object: nil)
}
func removeObserver(){
NSNotificationCenter.defaultCenter().removeObserver(self)
}
//MARK:- textfiled Delegate
func textFieldShouldBeginEditing(textField: UITextField) -> Bool
{
activeField = textField
return true
}
func textFieldShouldEndEditing(textField: UITextField) -> Bool
{
if activeField == textField
{
activeField = nil
}
return true
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
if txtUserName == textField
{
txtUserPassword.becomeFirstResponder()
}
else if (textField == txtUserPassword)
{
self.btnAdminLoginAction(nil)
}
return true;
}
func willChangeKeyboardFrame(aNotification : NSNotification)
{
if self.activeField != nil && self.activeField!.isFirstResponder()
{
if let keyboardSize = (aNotification.userInfo![UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
{
let dy = (self.activeField?.superview?.convertRect((self.activeField?.frame)!, toView: view).origin.y)!
let height = (self.view.frame.size.height - keyboardSize.size.height)
if dy > height
{
var frame = self.view.frame
frame.origin.y = -((dy - height) + (self.activeField?.frame.size.height)! + 20)
self.view.frame = frame
}
}
}
else
{
var frame = self.view.frame
frame.origin.y = 0
self.view.frame = frame
}
} }
Swift 5解决方案frédéric-adda:
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: UIResponder.keyboardWillShowNotification, object: nil, queue: nil) { [weak self] notification in
self?.keyboardWillShow(notification)
}
// Deal with rotations
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillChangeFrameNotification, object: nil, queue: nil) { [weak self] notification in
self?.keyboardWillShow(notification)
}
// Deal with keyboard change (emoji, numerical, etc.)
NotificationCenter.default.addObserver(forName: UITextInputMode.currentInputModeDidChangeNotification, object: nil, queue: nil) { [weak self] notification in
self?.keyboardWillShow(notification)
}
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, 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?[UIResponder.keyboardFrameEndUserInfoKey] 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中:
遵循KeyboardHandler协议
extension AnyViewController: KeyboardHandler {}
为屏幕上最后一个底部元素添加底部约束。
@IBOutlet var bottomConstraint: NSLayoutConstraint!
添加观察者订阅/取消订阅:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
startObservingKeyboardChanges()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
stopObservingKeyboardChanges()
}
享受吧!
Well, I think i might be too late but i found another simple version of Saqib's answer. I'm using Autolayout with constraints. I have a small view inside of another main view with username and password fields. Instead of changing the y coordinate of the view i'm saving the original constraint value in a variable and changing the constraint's constant to some value and again after the keyboard dismisses, i'm setting up the constraint to original one. This way it avoids the problem Saqib's answer has, (The view keeps on moving up and does not stop). Below is my code...
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);
self.originalConstraint = self.centerYConstraint.constant
}
func keyboardWillShow(sender: NSNotification) {
self.centerYConstraint.constant += 30
}
func keyboardWillHide(sender: NSNotification) {
self.centerYConstraint.constant = self.originalConstraint
}