[英]Sliding UIView When Keyboard Appears in iOS
我知道关于键盘出现在iOS上时滑动UIView的问题也很多。 但是,我的实现似乎有一个我未曾提及的问题。 发生幻灯片动画时,它不是从屏幕顶部开始,而是我从较低的原点开始,然后又向上移动到屏幕顶部。
这是我为实现此上滑行为而创建的类扩展。
public extension UIViewController {
private dynamic func keyboardWillShow(sender: NSNotification) {
if view.frame.origin.y == 0 {
slideViewVerticallyForKeyboardHeight(sender, directionUp: true)
}
}
private dynamic func keyboardWillHide(sender: NSNotification) {
if view.frame.origin.y < 0 {
slideViewVerticallyForKeyboardHeight(sender, directionUp: false)
}
}
private func slideViewVerticallyForKeyboardHeight(notification: NSNotification, directionUp: Bool) {
UIView.beginAnimations(nil, context: nil)
let keyboardHeight: CGFloat = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().height ?? 0.0
let animationDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue ?? 0.0
let animationCurve: Int = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey]?.integerValue ?? 0
UIView.setAnimationDuration(animationDuration)
UIView.setAnimationCurve(UIViewAnimationCurve(rawValue: animationCurve)!)
UIView.setAnimationBeginsFromCurrentState(true)
var newFrameRect = view.frame
if directionUp {
newFrameRect.origin.y -= keyboardHeight
newFrameRect.size.height += keyboardHeight
} else {
newFrameRect.origin.y += keyboardHeight
newFrameRect.size.height -= keyboardHeight
}
view.frame = newFrameRect
UIView.commitAnimations()
}
public func registerViewSlideOnKeyobard() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}
public func unregisterViewSlideOnKeyboard() {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
}
我不确定我缺少什么。 看我的view.frame值,我有一个负的origin.y,正如我期望的那样。 有人看到我想念的东西吗?
编辑 :aimak用户提出了一个非常明智的建议,即我将动画更改为(不推荐使用)块调用版本。 有趣的是,动画仍然被破坏,但是方式不同。 这是经过修改的代码,以及有关最新动画调用发生的情况的屏幕截图。
private func slideViewVerticallyForKeyboardHeight(notification: NSNotification, directionUp: Bool) {
UIView.beginAnimations(nil, context: nil)
let keyboardHeight: CGFloat = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().height ?? 0.0
let animationDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue ?? 0.0
let animationCurve: UIViewAnimationCurve = UIViewAnimationCurve(rawValue: notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey]?.integerValue ?? 0)!
var newFrameRect = view.frame
if directionUp {
newFrameRect.origin.y -= keyboardHeight
newFrameRect.size.height += keyboardHeight
} else {
newFrameRect.origin.y += keyboardHeight
newFrameRect.size.height -= keyboardHeight
}
UIView.animateWithDuration(animationDuration, delay: 0, options: animationCurve.toOptions(), animations: {
self.view.frame = newFrameRect
}, completion: nil)
}
这可能无法完全帮助您,但是自iOS 4+起不鼓励使用这些动画方法:
不鼓励在iOS 4.0及更高版本中使用此方法。 您应该改用基于块的动画方法来指定动画。
参考: https : //developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/clm/UIView/commitAnimations
您是否尝试过基于块的API?
编辑:这是自动布局的问题!
好的,我想我知道了:您是否使用自动版式? 如果是这样,则UIViewController.view的子视图可能具有view.top = 0的约束,并且该约束永远不会被破坏。 如果要获得所需的动画,请考虑:1.将每个子视图嵌入scrollView中(然后为contentOffet.y动画),或2.删除/编辑view.top约束。
正如aimak所指出的那样,问题在于我使用的是AutoLayout,并且约束覆盖了我对框架所做的修改。 为了解决这个问题,我将所有内容移到了滚动视图中。 现在,我利用滚动scrollview来在键盘显示时偏移。
这是我必须提供滚动行为的帮助器类。 请注意,我现在通过了滚动视图。
public class KeyboardScrollViewHelper {
private var scrollView: UIScrollView?
private var isScrolled = false
private dynamic func keyboardWillShow(sender: NSNotification) {
guard !isScrolled else {
return
}
slideViewVerticallyForKeyboardHeight(sender, directionUp: true)
}
private dynamic func keyboardWillHide(sender: NSNotification) {
guard isScrolled else {
return
}
slideViewVerticallyForKeyboardHeight(sender, directionUp: false)
}
private func slideViewVerticallyForKeyboardHeight(notification: NSNotification, directionUp: Bool) {
guard let scrollView = self.scrollView else {
return
}
let keyboardHeight: CGFloat = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().height ?? 0.0
let animationDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue ?? 0.0
let animationCurve: UIViewAnimationCurve = UIViewAnimationCurve(rawValue: notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey]?.integerValue ?? 0)!
var scrollViewOffset: CGFloat = 0
if directionUp {
scrollViewOffset = scrollView.contentOffset.y + keyboardHeight
isScrolled = true
} else {
scrollViewOffset = scrollView.contentOffset.y - keyboardHeight
isScrolled = false
}
scrollViewOffset = max(0, scrollViewOffset)
UIView.animateWithDuration(animationDuration, delay: 0, options: animationCurve.toOptions(), animations: {
scrollView.contentOffset.y = scrollViewOffset
}, completion: nil)
}
public func registerViewSlideOnKeyobard(scrollView: UIScrollView) {
self.scrollView = scrollView
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}
public func unregisterViewSlideOnKeyboard() {
scrollView?.contentOffset = CGPointZero
scrollView = nil
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.