我有一个应用,它在视图的下半部分有一个文本框。 这意味着当我在文本框中输入时,键盘会覆盖文本框。
我如何在打字时向上移动视图,这样我就可以看到我键入的内容,然后在键盘消失时将它移回原来的位置?
我到处都看了,但所有的解似乎都在Obj-C中,我还不能完全转换。
任何帮助都将不胜感激。
我有一个应用,它在视图的下半部分有一个文本框。 这意味着当我在文本框中输入时,键盘会覆盖文本框。
我如何在打字时向上移动视图,这样我就可以看到我键入的内容,然后在键盘消失时将它移回原来的位置?
我到处都看了,但所有的解似乎都在Obj-C中,我还不能完全转换。
任何帮助都将不胜感激。
当前回答
我注意到其他答案涉及从视图中删除一些顶部。如果你想简单地调整视图的大小而不削减任何内容,只需尝试这个方法:)
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.setTranslatesAutoresizingMaskIntoConstraints(true)
self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.height - keyboardSize.height)
}
}
func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.collectionView.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.height + keyboardSize.height)
}
}
其他回答
在这个线程中,一个流行的答案使用了以下代码:
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)
}
这个实现(Swift 4)将给你的行为最接近Android的默认行为。Ie:当活动文本域在键盘下时,将视图向上移动,当用户切换到另一个视图时,无需关闭键盘。记住调用settextfielddelegate()。
public class DelegateProxy: NSObject, UITextFieldDelegate {
private static let instance = DelegateProxies()
weak var activeTextField: UITextField?
var offset: CGFloat = 0
weak var vc: UIViewController?
var keyboardHeight: CGFloat = 0
public static func getDelegate(root: UIViewController) -> DelegateProxies {
instance.vc = root
return instance
}
public static func getDelegate() -> DelegateProxies {
return instance
}
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
self.activeTextField = textField
let globalPointY: CGFloat = (textField.superview?.convert(textField.frame.origin, to: nil).y ?? CGFloat(0)) + textField.frame.height
offset = UIScreen.main.bounds.height - globalPointY
if keyboardHeight > 0 {
vc?.moveViewUp(offsetFromKeyboard: keyboardHeight - offset)
}
return true
}
}
extension UIViewController {
private func setTextFieldDelegates(parentView: UIView) {
for child in parentView.subviews {
setTextFieldDelegates(parentView: child)
(child as? UITextField)?.delegate = DelegateProxies.getDelegate(root: self)
}
}
func registerAutoResizeOnKeyboardAppear(){
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)
}
func unregisterAutoResizeOnKeyboard(){
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
let offsetFromKeyboard = keyboardSize.height - DelegateProxies.getDelegate().offset
DelegateProxies.getDelegate().keyboardHeight = keyboardSize.height
moveViewUp(offsetFromKeyboard: offsetFromKeyboard)
}
}
func moveViewUp(offsetFromKeyboard: CGFloat){
print("offset from keyboard: \(offsetFromKeyboard)")
let moveOffset = offsetFromKeyboard + 8
if offsetFromKeyboard > 0 {
self.view.frame.origin.y = -moveOffset
}
if offsetFromKeyboard < 0 && view.frame.origin.y < 0 {
self.view.frame.origin.y += -moveOffset
if self.view.frame.origin.y > 0{
self.view.frame.origin.y = 0
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
self.view.frame.origin.y = 0
}
}
这个功能应该在Ios中内置,但是我们需要在外部做。 插入以下代码 *当textField在键盘下时移动视图, *当textField在键盘上方时不移动视图 *在需要时根据键盘的高度移动视图。 这在所有情况下都有效并经过测试。
import UIKit
class NamVcc: UIViewController, UITextFieldDelegate
{
@IBOutlet weak var NamTxtBoxVid: UITextField!
var VydTxtBoxVar: UITextField!
var ChkKeyPadDspVar: Bool = false
var KeyPadHytVal: CGFloat!
override func viewDidLoad()
{
super.viewDidLoad()
NamTxtBoxVid.delegate = self
}
override func viewWillAppear(animated: Bool)
{
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(TdoWenKeyPadVyd(_:)),
name:UIKeyboardWillShowNotification,
object: nil);
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(TdoWenKeyPadHyd(_:)),
name:UIKeyboardWillHideNotification,
object: nil);
}
func textFieldDidBeginEditing(TxtBoxPsgVar: UITextField)
{
self.VydTxtBoxVar = TxtBoxPsgVar
}
func textFieldDidEndEditing(TxtBoxPsgVar: UITextField)
{
self.VydTxtBoxVar = nil
}
func textFieldShouldReturn(TxtBoxPsgVar: UITextField) -> Bool
{
self.VydTxtBoxVar.resignFirstResponder()
return true
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
view.endEditing(true)
super.touchesBegan(touches, withEvent: event)
}
func TdoWenKeyPadVyd(NfnPsgVar: NSNotification)
{
if(!self.ChkKeyPadDspVar)
{
self.KeyPadHytVal = (NfnPsgVar.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().height
var NonKeyPadAraVar: CGRect = self.view.frame
NonKeyPadAraVar.size.height -= self.KeyPadHytVal
let VydTxtBoxCenVal: CGPoint? = VydTxtBoxVar?.frame.origin
if (!CGRectContainsPoint(NonKeyPadAraVar, VydTxtBoxCenVal!))
{
self.ChkKeyPadDspVar = true
UIView.animateWithDuration(1.0,
animations:
{ self.view.frame.origin.y -= (self.KeyPadHytVal)},
completion: nil)
}
else
{
self.ChkKeyPadDspVar = false
}
}
}
func TdoWenKeyPadHyd(NfnPsgVar: NSNotification)
{
if (self.ChkKeyPadDspVar)
{
self.ChkKeyPadDspVar = false
UIView.animateWithDuration(1.0,
animations:
{ self.view.frame.origin.y += (self.KeyPadHytVal)},
completion: nil)
}
}
override func viewDidDisappear(animated: Bool)
{
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
view.endEditing(true)
ChkKeyPadDspVar = false
}
}
|::|有时候视图会向下,在这种情况下使用高度+/- 150:
NonKeyPadAraVar.size.height -= self.KeyPadHytVal + 150
{ self.view.frame.origin.y -= self.KeyPadHytVal - 150},
completion: nil)
{ self.view.frame.origin.y += self.KeyPadHytVal - 150},
completion: nil)
我对初学者的两点建议: 在上面的例子中,有人改变坐标,其他人使用“自动调整蒙版”和其他约束:
正如苹果所说,不要将这三种逻辑混合在一起。 如果你在故事板中有约束,不要尝试改变x/y。这绝对行不通。
斯威夫特4.1
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0 {
self.view.frame.origin.y -= keyboardSize.height //can adjust as keyboardSize.height-(any number 30 or 40)
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
if self.view.frame.origin.y != 0 {
self.view.frame.origin.y = 0
}
}