Ce qui suit est une animation pour un champ de texte et une barre d'outils qui se déplacent vers le haut lorsque le clavier apparaît.
baseConstraint.constant = 211
self.view.setNeedsUpdateConstraints()
UIView.animateWithDuration(0.30, animations: {
self.view.layoutIfNeeded()
})
C'est proche mais pas tout à fait identique. Comment modifieriez-vous l'animation ci-dessus?
Modifier:
Voici le code final en utilisant la réponse ci-dessous!
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()
})
}
La réponse avec la durée variable est correcte et fonctionne iOS 3 à 8, mais avec la nouvelle version de Swift, le code de la réponse ne fonctionne plus . Peut-être que c'est une erreur de mon côté, mais je dois écrire:
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()
})
On dirait que objectForKey ne fonctionne plus et que la conversion est plus stricte.
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)
Mise à jour Swift 4, iOS 11+
Enregistrez d'abord la notification dans la méthode du cycle de vie d'une vue:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
}
Puis dans la méthode 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
}
Enfin, n'oubliez pas de supprimer observateur dans la méthode deinit
:
deinit {
NotificationCenter.default.removeObserver(self)
}
Premièrement, la réponse choisie est la bonne voie à suivre.
Plus peut être fourni ici est ce que l'animation est vraiment. Si vous imprimez toutes les CAAnimations dans le bloc UIViewAnimation, vous constaterez que il s'agit d'un CASpringAnimation lorsque vous définissez la courbe d'animation sur celle fournie dans la notification au clavier. La durée est 0.5 et les autres paramètres sont:
let ani = CASpringAnimation(keyPath: someKey)
ani.damping = 500
ani.stiffness = 1000
ani.mass = 3
ani.duration = 0.5
Le code ci-dessus peut reproduire l'animation avec précision.
Une fois que la courbe d'animation est définie sur celle du clavier, l'animation UIView ignorera la durée du paramètre. (Si vous voulez vraiment changer la durée, ajustez la valeur mass
.)
// tout d'abord déclarer un délégué dans votre classe UITextFieldDelegate
// Placer en haut du contrôleur de vue
// ****************** 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;
}
//
// Copie et contrôle la méthode déléguée de textfields dans votre classe
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()
}
Je voudrais signaler quelque chose qui m'a fait trébucher tout en résolvant ce problème. J'avais besoin de la taille du clavier en raison de la nouvelle vue "quickype" et de sa capacité à afficher/masquer (iOS8 uniquement). Voici comment j'ai fini par le résoudre:
- (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
}];
}