我有一个应用,它在视图的下半部分有一个文本框。 这意味着当我在文本框中输入时,键盘会覆盖文本框。
我如何在打字时向上移动视图,这样我就可以看到我键入的内容,然后在键盘消失时将它移回原来的位置?
我到处都看了,但所有的解似乎都在Obj-C中,我还不能完全转换。
任何帮助都将不胜感激。
我有一个应用,它在视图的下半部分有一个文本框。 这意味着当我在文本框中输入时,键盘会覆盖文本框。
我如何在打字时向上移动视图,这样我就可以看到我键入的内容,然后在键盘消失时将它移回原来的位置?
我到处都看了,但所有的解似乎都在Obj-C中,我还不能完全转换。
任何帮助都将不胜感激。
当前回答
不是广告、促销或垃圾邮件,只是一个很好的解决方案。我知道这个问题有近30个答案,我很震惊,居然没有人提到过这个美丽的GitHub项目,它为你做了这一切,甚至更好。所有的答案只是向上移动视图。我刚刚用这个IQKeyboardManager解决了我所有的问题。它有13000多颗恒星。 如果你使用swift,只需将此添加到你的podfile中
pod 'IQKeyboardManagerSwift'
然后在你的AppDelegate.swift中导入IQKeyboardManagerSwift
import IQKeyboardManagerSwift
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
IQKeyboardManager.shared.enable = true // just add this line
return true
}
}
添加一行IQKeyboardManager.shared.enable = true来启用它 如果您要进行生产,那么这个解决方案是必须的。
其他回答
对于Swift 3,我做了一个UIViewController子类,因为我需要在所有的视图控制器中恒定的行为。
class SomeClassVC: UIViewController {
//MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
addKeyboardObservers()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
removeKeyboardObservers()
}
//MARK: - Overrides
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
view.endEditing(true)
}
//MARK: - Help
func addKeyboardObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func removeKeyboardObservers() {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window)
}
func keyboardWillShow(notification: NSNotification) {
let keyboardHeight = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.height
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.window?.frame.origin.y = -1 * keyboardHeight!
self.view.layoutIfNeeded()
})
}
func keyboardWillHide(notification: NSNotification) {
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.view.window?.frame.origin.y = 0
self.view.layoutIfNeeded()
})
}
func resignTextFieldFirstResponders() {
for textField in self.view.subviews where textField is UITextField {
textField.resignFirstResponder()
}
}
func resignAllFirstResponders() {
view.endEditing(true)
}
}
对我有用
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
var isScroll = false
@objc func keyboardWillShow(sender: NSNotification) {
if( !isScroll ){
self.view.frame.origin.y -= 150
isScroll = true
}
}
@objc func keyboardWillHide(sender: NSNotification) {
if( isScroll ){
self.view.frame.origin.y += 150
isScroll = false
}
}
Swift 3更新…
正如其他人所说,你需要在控制器的viewDidLoad()方法中添加通知观察者,如下所示:
NotificationCenter.default.addObserver(forName: .UIKeyboardWillShow, object: nil, queue: nil)
{ notification in
self.keyboardWillShow(notification)
}
NotificationCenter.default.addObserver(forName: .UIKeyboardWillHide, object: nil, queue: nil)
{ notification in
self.keyboardWillHide(notification)
}
NotificationCenter.default.addObserver(forName: .UIKeyboardDidShow, object: nil, queue: nil)
{ _ in
self.enableUserInteraction()
}
NotificationCenter.default.addObserver(forName: .UIKeyboardDidHide, object: nil, queue: nil)
{ _ in
self.enableUserInteraction()
}
记得在适当的地方删除你的观察器(我在viewWillDisappear()方法中这样做)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidHide, object: nil)
然后,实现你的show和hide方法——注意告诉应用程序忽略交互事件的行(beginIgnoringInteractionEvents)。这很重要,因为如果没有它,用户可能会点击一个字段甚至滚动视图,导致第二次发生移位,从而导致可怕的UI故障。在键盘显示和隐藏之前忽略交互事件将防止这种情况:
func keyboardWillShow(notification: Notification)
{
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
{
UIApplication.shared.beginIgnoringInteractionEvents()
self.view.frame.origin.y -= keyboardSize.height
// add this line if you are shifting a scrollView, as in a chat application
self.timelineCollectionView.contentInset.top += keyboardSize.height
}
}
func keyboardWillHide(notification: Notification)
{
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
{
UIApplication.shared.beginIgnoringInteractionEvents()
self.view.frame.origin.y += keyboardSize.height
// add this line if you are shifting a scrollView, as in a chat application
self.timelineCollectionView.contentInset.top -= keyboardSize.height
}
}
最后,重新启用用户交互(记住,这个方法在键盘didShow或didHide之后触发):
func enableUserInteraction()
{
UIApplication.shared.endIgnoringInteractionEvents()
}
斯威夫特5.0:
经过4-5个小时的战斗,我得到了一个简单的扩展UIViewController与简单的代码,就像魅力
*当TextField在键盘上方时,视图不应该移动
*不需要设置常量值为NSLayoutConstraint
*无需第三方库
*无需动画代码
*适用于tableview
*这适用于自动布局/自动调整大小
extension UIViewController {
func addKeyboardObserver() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardNotifications(notification:)),
name: UIResponder.keyboardWillChangeFrameNotification,
object: nil)
}
func removeKeyboardObserver(){
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}
// This method will notify when keyboard appears/ dissapears
@objc func keyboardNotifications(notification: NSNotification) {
var txtFieldY : CGFloat = 0.0 //Using this we will calculate the selected textFields Y Position
let spaceBetweenTxtFieldAndKeyboard : CGFloat = 5.0 //Specify the space between textfield and keyboard
var frame = CGRect(x: 0, y: 0, width: 0, height: 0)
if let activeTextField = UIResponder.currentFirst() as? UITextField ?? UIResponder.currentFirst() as? UITextView {
// Here we will get accurate frame of textField which is selected if there are multiple textfields
frame = self.view.convert(activeTextField.frame, from:activeTextField.superview)
txtFieldY = frame.origin.y + frame.size.height
}
if let userInfo = notification.userInfo {
// here we will get frame of keyBoard (i.e. x, y, width, height)
let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let keyBoardFrameY = keyBoardFrame!.origin.y
let keyBoardFrameHeight = keyBoardFrame!.size.height
var viewOriginY: CGFloat = 0.0
//Check keyboards Y position and according to that move view up and down
if keyBoardFrameY >= UIScreen.main.bounds.size.height {
viewOriginY = 0.0
} else {
// if textfields y is greater than keyboards y then only move View to up
if txtFieldY >= keyBoardFrameY {
viewOriginY = (txtFieldY - keyBoardFrameY) + spaceBetweenTxtFieldAndKeyboard
//This condition is just to check viewOriginY should not be greator than keyboard height
// if its more than keyboard height then there will be black space on the top of keyboard.
if viewOriginY > keyBoardFrameHeight { viewOriginY = keyBoardFrameHeight }
}
}
//set the Y position of view
self.view.frame.origin.y = -viewOriginY
}
}
}
添加这个扩展的UIResponder得到哪个TextField被选中
extension UIResponder {
static weak var responder: UIResponder?
static func currentFirst() -> UIResponder? {
responder = nil
UIApplication.shared.sendAction(#selector(trap), to: nil, from: nil, for: nil)
return responder
}
@objc private func trap() {
UIResponder.responder = self
}
}
然后在你的任何ViewController中使用这个
override func viewWillAppear(_ animated: Bool) {
self.addKeyboardObserver()
}
override func viewWillDisappear(_ animated: Bool) {
self.removeKeyboardObserver()
}
在func viewWillAppear中注册这个通知(_ animated: Bool) 在func中注销此通知viewWillDisappear(_ animated:Bool) 下载演示文件
在这个线程中,一个流行的答案使用了以下代码:
func keyboardWillShow(sender: NSNotification) {
self.view.frame.origin.y -= 150
}
func keyboardWillHide(sender: NSNotification) {
self.view.frame.origin.y += 150
}
用一个静态量来抵消你的视图有一个明显的问题。它在一个设备上看起来很好,但在任何其他尺寸配置上看起来都很糟糕。您需要获取键盘高度并将其用作偏移值。
下面是一种适用于所有设备的解决方案,它可以处理用户在输入时隐藏预测文本字段的边缘情况。
解决方案
下面需要注意的是,我们将self.view.window作为对象参数传入。这将为我们提供来自键盘的数据,比如它的高度!
@IBOutlet weak var messageField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: self.view.window)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: self.view.window)
}
func keyboardWillHide(sender: NSNotification) {
let userInfo: [NSObject : AnyObject] = sender.userInfo!
let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
self.view.frame.origin.y += keyboardSize.height
}
我们将使它在所有设备上看起来都很漂亮,并处理用户添加或删除预测文本字段的情况。
func keyboardWillShow(sender: NSNotification) {
let userInfo: [NSObject : AnyObject] = sender.userInfo!
let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size
if keyboardSize.height == offset.height {
UIView.animateWithDuration(0.1, animations: { () -> Void in
self.view.frame.origin.y -= keyboardSize.height
})
} else {
UIView.animateWithDuration(0.1, animations: { () -> Void in
self.view.frame.origin.y += keyboardSize.height - offset.height
})
}
}
删除观察者
不要忘记在离开视图之前删除您的观察器,以防止传输不必要的消息。
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: self.view.window)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: self.view.window)
}
根据评论中的问题更新:
如果你有两个或更多的文本字段,你可以检查你的view.frame.origin.y是否为零。
func keyboardWillShow(sender: NSNotification) {
let userInfo: [NSObject : AnyObject] = sender.userInfo!
let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size
if keyboardSize.height == offset.height {
if self.view.frame.origin.y == 0 {
UIView.animateWithDuration(0.1, animations: { () -> Void in
self.view.frame.origin.y -= keyboardSize.height
})
}
} else {
UIView.animateWithDuration(0.1, animations: { () -> Void in
self.view.frame.origin.y += keyboardSize.height - offset.height
})
}
print(self.view.frame.origin.y)
}