it-swarm.com.de

Shake-Animation für UITextField/UIView in Swift

Ich versuche herauszufinden, wie das Textfeld beim Drücken auf die Taste durchgeschüttelt werden kann, wenn der Benutzer das Textfeld leer lässt.

Ich habe derzeit den folgenden Code:

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 {

}

Aber ich denke, es wäre viel ansprechender, wenn das Textfeld nur als Warnung angezeigt wird.

Ich kann nichts finden, um das Textfeld zu animieren.

Irgendwelche Ideen?

Vielen Dank!

50

Sie können duration und repeatCount ändern und anpassen. Das ist was ich in meinem Code verwende. Durch Variation von fromValue und toValue wird die im Shake zurückgelegte Entfernung variiert.

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")
118
rakeshbs

Die folgende Funktion wird in jeder Ansicht verwendet.

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")
    }
}
109
Surckarter

Oder Sie können dies verwenden, wenn Sie mehr Parameter wünschen ( in Swift 3 und 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")
    }  
}

Sie können diese Funktion auf jeder UIView, UIButton, UILabel, UITextView usw. aufrufen. Auf diese Weise

yourView.shake()

Oder auf diese Weise, wenn Sie der Animation einige benutzerdefinierte Parameter hinzufügen möchten:

yourView.shake(count: 5, for: 1.5, withTranslation: 10)
37
RomOne

Ich denke, das alles ist gefährlich. 

Wenn Ihre Shake-Animation auf einer Benutzeraktion basiert und diese Benutzeraktion während der Animation ausgelöst wird. 

CRAAAAAASH

Hier ist mein Weg in 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()
}

Vielleicht nicht die sauberste, aber diese Methode kann wiederholt ausgelöst werden und ist leicht zu verstehen

Bearbeiten:

Ich bin ein großer Befürworter des UIViewPropertyAnimators. So viele coole Funktionen, mit denen Sie grundlegende Animationen dynamisch modifizieren können.

Hier ein weiteres Beispiel, um einen roten Rand hinzuzufügen, während die Ansicht verwackelt wird, und dann zu entfernen, wenn der Schüttelvorgang beendet ist.

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()
}
18
Corey Pett

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")
        }
    }

Benutzen

self.vwOffer.shake()
9
Hardik Thakkar
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)
    }
}

Wie benutzt man:

[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])

}

// in die Basisklasse oder einen beliebigen View Controller schreiben und verwenden

1
Rana Ali Waseem

Dies basiert auf CABasicAnimation und enthält auch einen Audioeffekt:

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..")
        }
    }
}
0

Swift 5

Sichere Shake-Erweiterung (ohne Absturz) für Corey Pett Antworten:

extension UIView {
    func shake(for duration: TimeInterval = 0.5, withTranslation translation: CGFloat = 10) {
        let propertyAnimator = UIViewPropertyAnimator(duration: duration, dampingRatio: 0.3) {
            self.transform = CGAffineTransform(translationX: translation, y: 0)
        }

        propertyAnimator.addAnimations({
            self.transform = CGAffineTransform(translationX: 0, y: 0)
        }, delayFactor: 0.2)

        propertyAnimator.startAnimation()
    }
}
0
Vahid