J'essaie de comprendre comment rendre le texte secoué lorsque l'utilisateur laisse le champ vide.
J'ai actuellement le code suivant:
if self.subTotalAmountData.text == "" {
let alertController = UIAlertController(title: "Title", message:
"What is the Sub-Total!", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Okay", style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
} else {
}
Mais je pense que ce serait beaucoup plus attrayant d'avoir juste le champ de texte secouer comme une alerte.
Je ne trouve rien pour animer le champ de texte.
Des idées?
Merci!
Vous pouvez modifier duration
et repeatCount
et le modifier. C'est ce que j'utilise dans mon code. La variation de fromValue
et toValue
fera varier la distance parcourue pendant le tremblement.
let animation = CABasicAnimation(keyPath: "position")
animation.duration = 0.07
animation.repeatCount = 4
animation.autoreverses = true
animation.fromValue = NSValue(cgPoint: CGPoint(x: viewToShake.center.x - 10, y: viewToShake.center.y))
animation.toValue = NSValue(cgPoint: CGPoint(x: viewToShake.center.x + 10, y: viewToShake.center.y))
viewToShake.layer.add(animation, forKey: "position")
La fonction suivante est utilisée dans n'importe quelle vue.
extension UIView {
func shake() {
let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.duration = 0.6
animation.values = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0 ]
layer.add(animation, forKey: "shake")
}
}
Ou vous pouvez l'utiliser si vous voulez plus de paramètres ( dans Swift 3 et Swift 4 ):
public extension UIView {
func shake(count : Float = 4,for duration : TimeInterval = 0.5,withTranslation translation : Float = 5) {
let animation : CABasicAnimation = CABasicAnimation(keyPath: "transform.translation.x")
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.repeatCount = count
animation.duration = duration/TimeInterval(animation.repeatCount)
animation.autoreverses = true
animation.fromValue = NSValue(cgPoint: CGPoint(x: -translation, y: self.center.y))
animation.toValue = NSValue(cgPoint: CGPoint(x: translation, y: self.center.y))
layer.add(animation, forKey: "shake")
}
}
Vous pouvez appeler cette fonction sur n’importe quel UIView, UIButton, UILabel, UITextView, etc. De cette façon
yourView.shake()
Ou de cette manière si vous souhaitez ajouter des paramètres personnalisés à l'animation:
yourView.shake(count: 5, for: 1.5, withTranslation: 10)
Je pense que tout cela est dangereux.
Si votre animation est basée sur une action de l'utilisateur et que cette action est déclenchée pendant l'animation.
CRAAAAAASH
Voici mon chemin dans Swift 4 :
static func shake(view: UIView, for duration: TimeInterval = 0.5, withTranslation translation: CGFloat = 10) {
let propertyAnimator = UIViewPropertyAnimator(duration: duration, dampingRatio: 0.3) {
view.transform = CGAffineTransform(translationX: translation, y: 0)
}
propertyAnimator.addAnimations({
view.transform = CGAffineTransform(translationX: 0, y: 0)
}, delayFactor: 0.2)
propertyAnimator.startAnimation()
}
Peut-être pas la plus propre, mais cette méthode peut être déclenchée à plusieurs reprises et est facilement comprise
Modifier:
Je suis un grand partisan de l'utilisation de UIViewPropertyAnimator. Autant de fonctionnalités intéressantes vous permettant d'apporter des modifications dynamiques aux animations de base.
Voici un autre exemple permettant d’ajouter une bordure rouge lorsque la vue est agitée, puis de la supprimer une fois l’agitation terminée.
static func shake(view: UIView, for duration: TimeInterval = 0.5, withTranslation translation: CGFloat = 10) {
let propertyAnimator = UIViewPropertyAnimator(duration: duration, dampingRatio: 0.3) {
view.layer.borderColor = UIColor.red.cgColor
view.layer.borderWidth = 1
view.transform = CGAffineTransform(translationX: translation, y: 0)
}
propertyAnimator.addAnimations({
view.transform = CGAffineTransform(translationX: 0, y: 0)
}, delayFactor: 0.2)
propertyAnimator.addCompletion { (_) in
view.layer.borderWidth = 0
}
propertyAnimator.startAnimation()
}
Swift 3.0
extension UIView {
func shake(){
let animation = CABasicAnimation(keyPath: "position")
animation.duration = 0.07
animation.repeatCount = 3
animation.autoreverses = true
animation.fromValue = NSValue(cgPoint: CGPoint(x: self.center.x - 10, y: self.center.y))
animation.toValue = NSValue(cgPoint: CGPoint(x: self.center.x + 10, y: self.center.y))
self.layer.add(animation, forKey: "position")
}
}
Utiliser
self.vwOffer.shake()
extension CALayer {
func shake(duration: NSTimeInterval = NSTimeInterval(0.5)) {
let animationKey = "shake"
removeAnimationForKey(animationKey)
let kAnimation = CAKeyframeAnimation(keyPath: "transform.translation.x")
kAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
kAnimation.duration = duration
var needOffset = CGRectGetWidth(frame) * 0.15,
values = [CGFloat]()
let minOffset = needOffset * 0.1
repeat {
values.append(-needOffset)
values.append(needOffset)
needOffset *= 0.5
} while needOffset > minOffset
values.append(0)
kAnimation.values = values
addAnimation(kAnimation, forKey: animationKey)
}
}
Comment utiliser:
[UIView, UILabel, UITextField, UIButton & etc].layer.shake(NSTimeInterval(0.7))
func shakeTextField(textField: UITextField)
{
let animation = CABasicAnimation(keyPath: "position")
animation.duration = 0.07
animation.repeatCount = 3
animation.autoreverses = true
animation.fromValue = NSValue(cgPoint: CGPoint(x: textField.center.x - 10, y: textField.center.y))
animation.toValue = NSValue(cgPoint: CGPoint(x: textField.center.x + 10, y: textField.center.y))
textField.layer.add(animation, forKey: "position")
textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "",
attributes: [NSAttributedStringKey.foregroundColor: UIColor.red])
}
// écrit dans la classe de base ou n'importe quel contrôleur de vue et l'utilise
Ceci est basé sur CABasicAnimation, il contient également un effet audio:
extension UIView{
var audioPlayer = AVAudioPlayer()
func vibrate(){
let animation = CABasicAnimation(keyPath: "position")
animation.duration = 0.05
animation.repeatCount = 5
animation.autoreverses = true
animation.fromValue = NSValue(CGPoint: CGPointMake(self.center.x - 5.0, self.center.y))
animation.toValue = NSValue(CGPoint: CGPointMake(self.center.x + 5.0, self.center.y))
self.layer.addAnimation(animation, forKey: "position")
// audio part
do {
audioPlayer = try AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(mySoundFileName, ofType: "mp3")!))
audioPlayer.prepareToPlay()
audioPlayer.play()
} catch {
print("∙ Error playing vibrate sound..")
}
}
}