以下は、キーボードが表示されたときに上に移動するtextFieldとtoolBarのアニメーションです。
baseConstraint.constant = 211
self.view.setNeedsUpdateConstraints()
UIView.animateWithDuration(0.30, animations: {
self.view.layoutIfNeeded()
})
近いですが、完全に同一ではありません。上記のアニメーションをどのように変更しますか?
編集:
以下の答えを使用した最終コードです!
func keyboardWillShow(aNotification: NSNotification) {
let duration = aNotification.userInfo.objectForKey(UIKeyboardAnimationDurationUserInfoKey) as Double
let curve = aNotification.userInfo.objectForKey(UIKeyboardAnimationCurveUserInfoKey) as UInt
self.view.setNeedsLayout()
baseConstraint.constant = 211
self.view.setNeedsUpdateConstraints()
UIView.animateWithDuration(duration, delay: 0, options: UIViewAnimationOptions.fromMask(curve), animations: {
self.view.layoutIfNeeded()
}, completion: {
(value: Bool) in println()
})
}
KeyboardWillShow:通知のuserInfoディクショナリからアニメーション期間とアニメーション曲線を取得できます。
通知の最初の登録
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
次に、通知のuserInfoキーから値を取得します。
- (void)keyboardWillShow:(NSNotification*)notification {
NSNumber *duration = [notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSNumber *curve = [notification.userInfo objectForKey: UIKeyboardAnimationCurveUserInfoKey];
// Do stuff with these values.
}
これらのキーはさらに多くあり、UIKeyboardWillDismiss通知から取得することもできます。
この機能は、iOS 3.0にまで遡って利用できます:D
ここにドキュメントがあります:
あなたがそれを機能させるのを助ける必要があれば私に知らせてください。
迅速なバージョン:
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
func keyboardWillShow(aNotification: NSNotification) {
let duration = aNotification.userInfo.objectForKey(UIKeyboardAnimationDurationUserInfoKey) as NSNumber
let curve = aNotification.userInfo.objectForKey(UIKeyboardAnimationCurveUserInfoKey) as NSNumber
}
期間が可変の答えは正しく、iOS 3〜8で動作しますが、Swiftの新しいバージョンでは、答えのコードはもう動作しません。多分それは私の側の間違いですが、私は書く必要があります:
let duration = aNotification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as Double
let curve = aNotification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as UInt
self.view.setNeedsLayout()
//baseConstraint.constant = 211
self.view.setNeedsUpdateConstraints()
UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions(curve), animations: { _ in
//self.view.layoutIfNeeded()
}, completion: { aaa in
//(value: Bool) in println()
})
ObjectForKeyはもう機能していないようで、変換はより厳密です。
Swift3
let duration = noti.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
let curve = noti.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber
self.view.setNeedsLayout()
UIView.animate(withDuration: TimeInterval(duration), delay: 0, options: [UIViewAnimationOptions(rawValue: UInt(curve))], animations: {
self.view.layoutIfNeeded()
}, completion: nil)
Swift 4アップデート、iOS 11以降
ビューのライフサイクルメソッドで最初に通知に登録します。
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
}
次にkeyBoardWillShow
メソッドで:
@objc func keyBoardWillShow(notification: NSNotification) {
guard let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double else {return}
print(duration) // you got animation's duration safely unwraped as a double
}
最後に、deinit
メソッドでオブザーバーを削除することを忘れないでください:
deinit {
NotificationCenter.default.removeObserver(self)
}
まず、選択した答えが正しい方法です。
ここで提供できるのは、アニメーションが実際に何であるかです。 UIViewAnimationブロック内のすべてのCAAnimationsを印刷すると、アニメーション通知をキーボード通知で提供されているものに設定するときに、CASpringAnimationになります。期間は0.5で、その他のパラメーターは次のとおりです。
let ani = CASpringAnimation(keyPath: someKey)
ani.damping = 500
ani.stiffness = 1000
ani.mass = 3
ani.duration = 0.5
上記のコードは、アニメーションを正確に再現できます。
アニメーションカーブがキーボードカーブに設定されると、UIViewアニメーションはパラメータの期間を無視します。 (期間を本当に変更したい場合は、mass
値を調整します。)
//まず、クラスUITextFieldDelegateでデリゲートを宣言します
// View Controllerの上部に配置
// ****************** Keyboard Animation ***************
var animateDistance = CGFloat()
struct MoveKeyboard {
static let KEYBOARD_ANIMATION_DURATION : CGFloat = 0.3
static let MINIMUM_SCROLL_FRACTION : CGFloat = 0.2;
static let MAXIMUM_SCROLL_FRACTION : CGFloat = 0.8;
static let PORTRAIT_KEYBOARD_HEIGHT : CGFloat = 216;
static let LANDSCAPE_KEYBOARD_HEIGHT : CGFloat = 162;
}
//
//クラス内のテキストフィールドデリゲートメソッドをコピーしてペストします
func textFieldDidBeginEditing(textField: UITextField) {
let textFieldRect : CGRect = self.view.window!.convertRect(textField.bounds, fromView: textField)
let viewRect : CGRect = self.view.window!.convertRect(self.view.bounds, fromView: self.view)
let midline : CGFloat = textFieldRect.Origin.y + 0.5 * textFieldRect.size.height
let numerator : CGFloat = midline - viewRect.Origin.y - MoveKeyboard.MINIMUM_SCROLL_FRACTION * viewRect.size.height
let denominator : CGFloat = (MoveKeyboard.MAXIMUM_SCROLL_FRACTION - MoveKeyboard.MINIMUM_SCROLL_FRACTION) * viewRect.size.height
var heightFraction : CGFloat = numerator / denominator
if heightFraction > 1.0 {
heightFraction = 1.0
}
let orientation : UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation
if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown) {
animateDistance = floor(MoveKeyboard.PORTRAIT_KEYBOARD_HEIGHT * heightFraction)
} else {
animateDistance = floor(MoveKeyboard.LANDSCAPE_KEYBOARD_HEIGHT * heightFraction)
}
var viewFrame : CGRect = self.view.frame
viewFrame.Origin.y -= animateDistance
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(NSTimeInterval(MoveKeyboard.KEYBOARD_ANIMATION_DURATION))
self.view.frame = viewFrame
UIView.commitAnimations()
}
func textFieldDidEndEditing(textField: UITextField) {
var viewFrame : CGRect = self.view.frame
viewFrame.Origin.y += animateDistance
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(NSTimeInterval(MoveKeyboard.KEYBOARD_ANIMATION_DURATION))
self.view.frame = viewFrame
UIView.commitAnimations()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
Swift 4
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
func keyboardWillShow(notification: NSNotification) {
let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]
print("duration",duration)
}
//--------------------------------------------------------------
// MARK: -
// MARK: - UITextFieldDelegate
//--------------------------------------------------------------
//To trigger event when user types in fields
//right click in IB and choose EditingChanged >> textField_EditingChanged
//NOTE IF KEYBOARD NOT SHOWING IN SIMULATOR and no view appearing ITS TURNED OFF BY DEFAULT SO YOU CAN TYPE WITH YOUR MAC KEYBOARD - HIT CMD+K or Simulator > Menu > Toggle Software Keyboard...
@IBAction func textField_EditingChanged(textField: UITextField) {
//if more than one search
if(textField == self.textFieldAddSearch){
appDelegate.log.error("self.textFieldAddSearch: '\(self.textFieldAddSearch.text)'")
if textField.text == ""{
}else{
callJSONWebservices(textField.text)
}
}else{
appDelegate.log.error("textFieldDidBeginEditing: unhandled textfield")
}
}
//TWO WAYS TO HIDE THE VIEW
//textFieldShouldReturn
//buttonCancel_Action
//USER HIT RETURN BUTTON ON keyboard >> resignFirstResponder >> triggers keyboardWillHide
func textFieldShouldReturn(textField: UITextField)-> Bool{
//triggers keyboardWillHide: which also fades out view
self.textFieldAddSearch.resignFirstResponder()
return false
}
//--------------------------------------------------------------
// MARK: -
// MARK: - KEYBORAD
//--------------------------------------------------------------
private func subscribeToKeyboardNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}
private func unsubscribeFromKeyboardNotifications() {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWillShow(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let heightKeyboard = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().height {
if let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue {
self.viewAddNewSearchResults.alpha = 0.0
self.viewAddNewSearchResults.hidden = false
if let curve = userInfo[UIKeyboardAnimationDurationUserInfoKey]?.integerValue {
appDelegate.log.info("keyboardWillShow: duration:\(duration)")
UIView.animateWithDuration(duration, delay:0.0, options: .CurveEaseInOut,
animations: {
//self.view.frame = CGRectMake(0, 0, Geo.width(), Geo.height() - height)
self.viewAddNewSearchResults_BottomConstraint.constant = heightKeyboard;
self.viewAddNewSearchResults.alpha = 1.0
},
completion: nil)
}
}
}
}
}
func keyboardWillHide(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let heightKeyboard = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().height {
if let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey]?.doubleValue {
if let curve = userInfo[UIKeyboardAnimationDurationUserInfoKey]?.integerValue {
appDelegate.log.info("keyboardWillHide: duration:\(duration)")
UIView.animateWithDuration(duration, delay:0.0, options: .CurveEaseInOut,
animations: {
self.viewAddNewSearchResults_BottomConstraint.constant = 0;
self.viewAddNewSearchResults.alpha = 0.0
},
completion: nil)
}
}
}
}
}
//Add button shows search result panel below search text fields
//just set focus in the textField
//then the keyboardWillShow will fade in the view and resize it to fit above the keyboard
//and match fade in duration to animation of keyboard moving up
@IBAction func buttonAdd_Action(sender: AnyObject) {
//triggers keyboardWillHide: which also fades out view
self.textFieldAddSearch.resignFirstResponder()
}
//TWO WAYS TO HIDE THE VIEW
//textFieldShouldReturn
//buttonCancel_Action
//Cancel on the search results - just resignFirstResponder >> triggers keyboardWillHide: which also fades out view
@IBAction func buttonCancel_Action(sender: AnyObject) {
//triggers keyboardWillHide: which also fades out view
self.textFieldAddSearch.resignFirstResponder()
}
この問題を解決する際に私をつまずかせたものを指摘したいと思います。新しい "quickype"ビューとその表示/非表示機能のために、キーボードのsizeが必要でした(iOS8のみ)。これは私がそれを解決する方法です:
- (void)keyboardWillChangeFrame:(NSNotification *)notification {
NSValue *value = notification.userInfo[UIKeyboardFrameEndUserInfoKey];
self.keyboardFrame = [value CGRectValue];
NSTimeInterval duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
[UIView animateWithDuration:duration animations:^{
//ANIMATE VALUES HERE
}];
}