可能在屏幕底部有一个按钮,随着iOS键盘的弹出而向上移动。
可能在屏幕底部有一个按钮,随着iOS键盘的弹出而向上移动。
我正在使用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")
}
}
在现有答案的基础上有一些改进可以进行。
首先,UIKeyboardWillChangeFrameNotification可能是最好的通知,因为它处理的不仅是显示/隐藏的变化,还包括由于键盘更改(语言、使用第三方键盘等)和旋转(但请注意下面的评论指出键盘将隐藏应该也要处理以支持硬件键盘连接)引起的变化。
其次,动画参数可以从通知中获取,以确保动画正确地进行。
这段代码可以进行一些清理,特别是如果你对字典代码的强制解包感到满意的话。
class MyViewController: UIViewController {
// This constraint ties an element at zero points from the bottom layout guide
var keyboardHeightLayoutConstraint: NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self,
selector: #selector(self.keyboardNotification(notification:)),
name: UIResponder.keyboardWillChangeFrameNotification,
object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
func keyboardNotification(notification: NSNotification) {
guard let userInfo = notification.userInfo else { return }
let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let endFrameY = endFrame?.origin.y ?? 0
let duration:TimeInterval = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue
let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw)
if endFrameY >= UIScreen.main.bounds.size.height {
self.keyboardHeightLayoutConstraint?.constant = 0.0
} else {
self.keyboardHeightLayoutConstraint?.constant = endFrame?.size.height ?? 0.0
}
UIView.animate(
withDuration: duration,
delay: TimeInterval(0),
options: animationCurve,
animations: { self.view.layoutIfNeeded() },
completion: nil)
}
}
哈喽-lord, 我认为animateWithDuration
实际上什么都没做。尝试将持续时间更改为10.0
秒,甚至只是注释掉整个动画调用,并只运行self.view.layoutIfNeeded()
。对我来说,它似乎被键盘自己的动画覆盖了。也许iOS在调用键盘通知之后调用commitAnimation
。
.f77:您是否更改了已经在您要进行动画的底部位置的约束?这行是关键,约束不应为nil
。动画块中的self.view.layoutIfNeeded
应用了更新后的约束。
很好。但是当键盘隐藏时,我发现这不起作用,因为endFrame?.size.height
不为空。我得到的结束框架是UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 1024}, {768, 264}}";
。在iOS 8.3 iPad模拟器上运行的,竖屏,Xcode6.3 beta4。
如果隐藏键盘时是这样的结束帧,听起来键盘是从屏幕上动画移开的,但实际上没有缩小。您可能需要获取窗口大小来确切知道1024是屏幕底部。然后,需要将约束常量设置为屏幕高度 - 结束框架的y坐标。
如果键盘不隐藏,请尝试使用此代码:如果endFrame?.origin.y >= UIScreen.mainScreen().bounds.size.height { self.keyboardHeightLayoutConstraint?.constant = 0.0 } else { self.keyboardHeightLayoutConstraint?.constant = endFrame.size.height }
当键盘被解除时,它似乎没有重置视图。这可能只是我约束的一个整体错误,但是是的:S
keyBoardHeightLayoutConstraint是在InterfaceBuilder中定义的一个约束,将您希望移动/缩小的底部内容与底部布局指南或视图控制器的主视图的底部相关联。常量最初设置为零,并将根据键盘的出现或更改大小进行调整。
到目前为止,对我来说效果最好。我建议在开始时读取约束的初始常量:var keyboardHeightLayoutConstraintConstant: CGFloat? = 0 ... override func viewDidAppear(animated: Bool) { self.keyboardHeightLayoutConstraintConstant = self.keyboardHeightLayoutConstraint?.constant } ... func keyboardNotification(notification: NSNotification) { .... self.keyboardHeightLayoutConstraint?.constant = endFrame?.size.height ?? 0.0 self.keyboardHeightLayoutConstraint?.constant += keyboardHeightLayoutConstraintConstant!
我没有阅读底部的“请注意”部分,只是意识到解决了我的问题,即键盘仅仅是转换而不是缩小!谢谢。
约束在键盘消失后不会到零
由于某种原因,当键盘消失时,视图将与键盘一起进行动画,但是当键盘出现时,动画会被跳过...即使处理两者的代码相同,相当奇怪。如果我使用UIKeyboardDidChangeFrameNotification,它就可以正常工作,但是动画会延迟,因为键盘必须首先完成其动画
好吧,不要紧,只是模拟器的傻瓜,它在设备上完美运行
这对我来说效果很好...谢谢!但是当我点击外部使键盘消失时,视图会向下移动。我该怎么办?
请注意,即使iOS键盘消失,当连接硬件键盘时,.UIKeyboardWillChangeFrame仍不会触发。您还需要观察.UIKeyboardWillHide以捕获这种情况。
发现了问题,您有建议的修改吗?是否仅需要添加额外的观察者,或者需要更新处理代码?我现在没有时间进行实验。
工作正常...但是,当键盘与键盘分离或分离时,iPad上会有一些小问题...有什么好的解决这两种特殊情况的方法吗?
我遇到了您说的在出现时键盘不进行动画的问题,但在iOS 10中消失时仍然正常工作。在我更新到iOS 10之前,它一直正常工作。您的设备在新的升级中是否仍然正常工作?
嗨,这个完美地解决了我的问题!这是我在寻找的答案,但是当我点击外部使键盘消失时,视图会向下移动。我该怎么办?
请注意,.UIKeyboardWillChangeFrame
在连接硬件键盘时不会触发,即使iOS键盘消失。您还需要观察.UIKeyboardWillHide
以捕获这种情况。
很好的发现,您有提出的修改吗?是添加额外的观察者就足够了,还是处理代码也需要更新?我现在没有时间进行实验。
效果不错..我的问题是它比键盘高了一点点。有什么办法可以解决这个问题吗?
这段代码对我不起作用,所以我只是删除了if/else,并用self.<enterbuttonname>.frame.origin.y = endFrameY - self.<enterbuttonname>.frame.height
替换了它
有几个CocoaPods提供了强大的键盘避免解决方案。我推荐使用github.com/IdleHandsApps/IHKeyboardAvoiding,当然,我推荐它,因为我写了它 🙂
我一直在努力解决文本视图的动画问题。对我来说,UIKeyboardWillChangeFrame解决了这个问题。与keyboardDidShowNotification或keyboardWillShowNotification通知相比,它使用这个通知完美地工作。请将UIKeyboardWillChangeFrame加粗以突出显示。
对于通过UI创建的控件,我该如何操作?我只需在视图控制器中定义一个let bottomConstraint
,然后将其添加到NSLayoutConstraint.activate[]
中吗?
已经弄明白了,将会提供一个新的答案。但是在设置约束时进行了更正。self.keyboardHeightLayoutConstraint?.constant = endFrame?.size.height ?? 0.0
应该是self.discussionsMessageBoxBottomAnchor.constant = -1 * (endFrame?.size.height ?? 0.0)
我认为这取决于约束的创建顺序。在iOS具有锚点之前,原始答案是编写的(或者只是您给约束起的名字)。
锚点是NSLayoutConstraint。但是约束是基于锚点:view.bottomAnchor
问题:如何在iOS键盘弹出时将屏幕底部的按钮向上移动?
原因:键盘弹出时,按钮被键盘遮挡,导致用户无法点击。
解决方法:在键盘弹出时,将视图向上移动,以便按钮可见。
解决代码如下(Swift 4):
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(sender:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(sender:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
@objc func keyboardWillShow(sender: NSNotification) {
self.view.frame.origin.y = -150 // 将视图向上移动150个点
}
@objc func keyboardWillHide(sender: NSNotification) {
self.view.frame.origin.y = 0 // 将视图恢复到原始位置
}
这个方法简单有效,但如果有多个文本框,可以添加一个`keyboardShowing`布尔值,只在键盘显示时移动一次。另外,也可以将移动操作应用于文本框而不是整个视图,这样可以避免在切换输入语言时出现问题。
如果在隐藏键盘时视图仍然保持移动状态,可能是由于添加了约束常量。解决方法是将移动操作应用于文本框的约束值而不是整个视图。
如果希望移动过渡更加平滑,可以使用动画效果。关于如何实现动画效果,可以参考以下问题:stackoverflow.com/questions/25693130/…。
另外,如果在切换不同文本框时,视图持续移动并导致文本框超出屏幕范围,可以修改代码,使视图在每次触摸新的文本框时只移动一次,而不是每次都移动150个点。
以上是解决在iOS键盘弹出时将屏幕底部按钮向上移动的原因和解决方法的整理。
问题的出现原因:
- 使用了Auto Layout的情况下,设置了Bottom Space to Superview的约束;
- 没有为约束创建IBOutlet;
- 没有注册UIKeyboardWillShowNotification通知。
解决方法:
- 为约束创建IBOutlet,并将约束的值更新为键盘高度加上一定偏移量;
- 当键盘消失时,将约束的值重置为初始值;
- 注册UIKeyboardWillShowNotification通知。
如果不使用Auto Layout,可以考虑使用类似IHKeyboardAvoiding这样的第三方库来解决问题。
代码示例:
// 创建IBOutlet
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
// 注册通知
func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
}
// 键盘弹出时更新约束值
func keyboardWasShown(notification: NSNotification) {
let info = notification.userInfo!
let keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue()
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.bottomConstraint.constant = keyboardFrame.size.height + 20
self.view.layoutIfNeeded()
})
}
// 键盘消失时重置约束值
func keyboardWillBeHidden(notification: NSNotification) {
UIView.animate(withDuration: 0.1, animations: { () -> Void in
self.bottomConstraint.constant = 0
self.view.layoutIfNeeded()
})
}
以上是解决该问题的原因和方法,希望对你有所帮助。