[英]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.