问答中心分类: IOS使用Swift通过键盘移动视图
0
匿名用户 提问 11小时 前

我有一个应用程序,在视图的下半部分有一个文本字段。
我该如何在键入时向上移动视图,以便看到我正在键入的内容,然后在键盘消失时将其向下移动到原始位置?
我到处都找过了,但所有的解决方案似乎都在Obj-C中,我现在还不能完全转换。
任何帮助都将不胜感激。

29 Answers
0
gammachill 回答 11小时 前

最简单的方法甚至不需要任何代码:

  1. 下载键盘布局约束。敏捷的如果尚未使用Spring动画框架,请将文件添加(拖放)到项目中。
  2. 在情节提要中,为视图或文本字段创建底部约束,选择约束(双击它),然后在标识检查器中,将其类从NSLayoutConstraint更改为KeyboardLayoutConstraint。
  3. 完成!

对象将与键盘同步自动上移。

gammachill 回复 11小时 前

要选择底部约束,也可以转到“尺寸检查器”,然后双击列表中的约束-raywenderlich。com/wp-content/uploads/2015/09/…

Brian 回复 11小时 前

这对我来说效果很好。这实际上是一个两步的过程。1、添加KeyboardLayoutConstraint。斯威夫特,2。在情节提要中,为视图或文本字段创建底部约束。注意:我删除了我的约束,只在视图或文本字段的底部添加了一个约束,并将其类从NSLayoutConstraint更改为KeyboardLayoutConstraint。然后是上面的任何视图/文本字段等。我只是用一个KeyboardLayoutConstraint将该项目的约束连接到该项目,结果是当键盘出现/消失时,视图中的所有项目都上移/下移

miguelSantirso 回复 11小时 前

这是最佳解决方案,提供的代码不会硬编码任何值,例如动画的长度或曲线,或键盘的大小。这也很容易理解。

Clifton Labrum 回复 11小时 前

这对我来说是可行的,但我在键盘顶部和滚动视图底部之间有一个额外的50px的空间。我想知道这是否是由于我使用的安全区域底部约束。有人碰到这个吗?

Ely Dantas 回复 11小时 前

如果视图居中,请在Y轴上设置优先级750,然后添加KeyboardLayoutConstraint子类底部约束。

ScottyBlades 回复 11小时 前

这是一个很棒的答案。设计也很酷。建议:如果您的文本视图/文本字段位于表视图单元格上,您可能会注意到,每当用户单击enter并转到下一个文本字段时,具有此约束的视图都会笨拙地跳转。可以将动画包装在DispatchQueue.main.async {}来修复它。干得好!竖起大拇指!

btrballin 回复 11小时 前

答案很棒,但我有一个特例,我有一个表格视图,其中一个单元格包含文本区域,所以它将表格视图向上推,但不是整个单元格

Neph 回复 11小时 前

@CliftonLabrum我也遇到了同样的问题,因为这个原因,我的一个按钮的高度自动降低了(decribed)在这里). :/ 你找到解决办法了吗?

anoop4real 回复 11小时 前

我发现了一个问题,观察者没有被移除,类中的deinit从未被调用。。。我试着按程序添加这个类

Ethan Brimhall 回复 11小时 前

这是最好的答案。除此之外,其他解决方案都不适用于我!

Amit Samant 回复 11小时 前

@CliftonLabrum将UpdateConstraint函数替换为swift func updateConstant() { let safeAreaBottom = UIApplication.appDelegate.window?.safeAreaInsets.bottom ?? 0 let height: CGFloat if keyboardVisibleHeight > 0 { height = keyboardVisibleHeight - safeAreaBottom } else { height = 0 } self.constant = offset + height }此外,我还有一个方便的app-delegate访问器,如果你在ios 13上,它会给我提供窗口,确保你从scenedelegate那里获得窗口对象

Kian 回复 11小时 前

请注意,为了使其正常工作第一项约束必须是视图中的参考点(例如Superview.Bottom)和第二项必须是视图或文本字段或任何内容的底部。如果相反,则当键盘出现时,视图/文本字段向下移动,而不是向上移动。

0
Dan Beaulieu 回答 11小时 前

此线程上的一个常见答案使用以下代码:

func keyboardWillShow(sender: NSNotification) {
    self.view.frame.origin.y -= 150
}
func keyboardWillHide(sender: NSNotification) {
    self.view.frame.origin.y += 150
}

用静态量抵消视图存在一个明显的问题。它在一个设备上看起来不错,但在任何其他尺寸的配置上看起来都不好。您需要获取键盘高度,并将其用作偏移值。
这里有一个解决方案适用于所有设备并处理用户在键入时隐藏预想文本字段的边缘情况。
解决方案
下面需要注意的是,我们正在传递self。看法窗口作为我们的对象参数。这将为我们提供来自键盘的数据,例如它的高度!

@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)
}

根据评论中的问题更新:
如果您有两个或多个文本字段,可以检查您的视图。框架起源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)
}
Mugunthan Balakrishnan 回复 11小时 前

处理多个文本字段时,视图会不断向上移动,不会再向下移动

Dan Beaulieu 回复 11小时 前

您必须更改条件以考虑文本字段

Mugunthan Balakrishnan 回复 11小时 前

谢谢你的回复,我找到了这个堆栈溢出线程的答案堆栈溢出。com/questions/1126726/…

Dan Beaulieu 回复 11小时 前

@MugunthanBalakrishnan感谢您提出这个问题,我添加了一个解决方案。

rudald 回复 11小时 前

嗨,伙计们,有一个bug。在视图中调用观察者后,观察者不会从视图中移除。将此行“NSNotificationCenter.defaultCenter().removeObserver(self,名称:UIKeyboardWillHideNotification,对象:self.view.window)”替换为“NSNotificationCenter.defaultCenter()。removeObserver(self,名称:UIKeyboardWillHideNotification,对象:nil)”,然后删除观察者

0
weegee 回答 11小时 前

不是广告、促销或垃圾邮件,这是一个很好的解决方案。我知道这个问题有将近30个答案,我很震惊,甚至没有人提到过一次这个漂亮的GitHub项目这一切都对你有利,甚至更好。所有答案都只是将视图向上移动。我刚刚解决了这个IQKeyboardManager的所有问题。它有13000多颗星。
如果您使用swift,只需将其添加到您的podfile中即可

pod 'IQKeyboardManagerSwift'

然后在AppDelegate中。swift doimport 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启用它
如果你要生产,这个解决方案是必须的。

Dhanu K 回复 11小时 前

这真的很好,但最新版本不适合我,我使用了6.2.1,导入为import IQKeyboardManager并已使用IQKeyboardManager.shared().isEnabled = true在AppDelegate中

Dhanu K 回复 11小时 前

这在使用多个编辑文本时效果非常好,这节省了我的时间

zeeshan 回复 11小时 前

非常感谢你指出了这个很棒的图书馆。这个库最终解决了所有与键盘相关的废话,而苹果从未为这些废话提供过解决方案。现在,我将在我所有的项目中使用它,新的和旧的,节省时间和头痛这个键盘出现,消失或不消失,或如何隐藏它,为什么它是重叠的,问题一直造成我从那天起,我为iPhone编程。

adougies 回复 11小时 前

@DhanuK,刚刚找到这个库,它工作得很完美,而且很轻松。应用程序代理代码已更新为IQKeyboardManager。共享。启用=true

J.C 回复 11小时 前

这个答案需要更高,更高。

Wahab Khan Jadon 回复 11小时 前

我已经在使用它了,但当键盘崩溃时,视图不会移回其原始位置。。。IQKeyboardManager.shared.layoutIfNeededOnUpdate = true添加此行也可以解决我的问题。。。

oskarko 回复 11小时 前

这应该是公认的答案!这是最好的!!

Mohammad Bashir Sidani 回复 11小时 前

这纯粹是天才

0
scipianne 回答 11小时 前

我对其中一个答案进行了一些改进,使其能够在一个页面上使用不同的键盘和不同的文本视图/字段:
添加观察员:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

func keyboardWillHide() {
    self.view.frame.origin.y = 0
}

func keyboardWillChange(notification: NSNotification) {

    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        if YOURTEXTVIEW.isFirstResponder {
            self.view.frame.origin.y = -keyboardSize.height
        }
    }
}

删除观察者:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
Masih 回复 11小时 前

这个解决方案比公认的答案更有效。公认的答案只显示了一次键盘,这对我来说是一个错误:)

zeeshan 回复 11小时 前

这适用于Xcode 10.1和iOS 12。接受的答案不再有效。

Munib 回复 11小时 前

这是一个很好的答案,我要添加的唯一一件事是跟踪较新设备(X、XS等)中的底部安全区域,以便对此进行解释。

Antzi 回复 11小时 前

@Munib见堆栈溢出。com/a/54993623/1485230其他问题包括视图未设置动画,以及未遵循键盘高度更改。

Saifan Nadaf 回复 11小时 前

如果我的文本字段是视图的顶部,该怎么办。。?我的意思是,如果有原点为Y=0的文本字段。。??然后textField上升了,我看不到

0
user3677173 回答 11小时 前

将其添加到viewcontroller。工作起来很有魅力。只需调整值。

override func viewDidLoad() {
    super.viewDidLoad()        
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name:NSNotification.Name.UIKeyboardWillShow, object: nil);
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name:NSNotification.Name.UIKeyboardWillHide, object: nil);
}

@objc func keyboardWillShow(sender: NSNotification) {
    self.view.frame.origin.y -= 150
}
@objc func keyboardWillHide(sender: NSNotification) {
    self.view.frame.origin.y += 150
}
DannieCoderBoi 回复 11小时 前

这对我来说很有用。然而,它有点不稳定。我怎样才能把这个搬到斯莫斯利去?还有一种方法可以只将其应用于其中一个文本字段,因为它目前对所有文本字段都适用(

user3677173 回复 11小时 前

你可以使用UIView。animateWithDuration(1.0,动画:{self.view.frame.origin.y-=150},完成:nil)

Teodor Ciuraru 回复 11小时 前

它可能不适用于“自动布局”,因此如果是这样,请考虑停用它。

Mike 回复 11小时 前

这会导致自动布局出现一些奇怪的行为@Josh,你错了

Mike 回复 11小时 前

如果使用自动布局,请确保调用self.view.setTranslatesAutoresizingMaskIntoConstraints(true)在你搬进去之前self.view.setTranslatesAutoresizingMaskIntoConstraints(false)在你搬回去之前

Josh 回复 11小时 前

@迈克,它在这里工作,我很高兴,显然,我没有错。时髦的东西是xCode的日常饮水和面包。我不是iOS专家,所以我不能争论更多的是我的眼睛看到了什么。作为记录,我使用的是Xcode 6.3和autolayout。并构建到iOS 8.3

V_J 回复 11小时 前

这对我不起作用。从一个UITextField移动到另一个UITextField后,屏幕变黑。

user3677173 回复 11小时 前

这取决于布局。约束可能会弄乱框架。

nielsbot 回复 11小时 前

不要这样做!你不能假设键盘有一定的尺寸。

xtrinch 回复 11小时 前

应使用键盘大小。当设备上有附件视图和不同的键盘高度时,会发生什么?分离的键盘?