it-swarm.com.ru

Анимация встряхивания для UITextField/UIView в Swift

Я пытаюсь понять, как заставить текстовое поле трястись при нажатии кнопки, когда пользователь оставляет текстовое поле пустым.

В настоящее время у меня работает следующий код:

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 {

}

Но я думаю, что было бы гораздо более привлекательным просто трясти текстовое поле в качестве предупреждения.

Я не могу найти ничего, чтобы оживить текстовое поле.

Есть идеи?

Спасибо!

50
Joe CRONE Scrivens

Вы можете изменить duration и repeatCount и настроить его. Это то, что я использую в своем коде. Варьирование fromValue и toValue будет варьировать расстояние, которое перемещается при встряхивании.

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

Следующая функция используется в любом представлении.

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

Или вы можете использовать это, если вам нужно больше параметров ( в Swift 3 и 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")
    }  
}

Вы можете вызвать эту функцию на любом UIView, UIButton, UILabel, UITextView и т.д. Таким образом

yourView.shake()

Или так, если вы хотите добавить некоторые пользовательские параметры для анимации:

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

Я думаю, что все это опасно. 

Если ваша анимация встряхивания основана на пользовательском действии, и это пользовательское действие запускается во время анимации. 

CRAAAAAASH

Вот мой путь в 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()
}

Может быть, не самый чистый, но этот метод может быть запущен многократно и легко понять

Правка:

Я огромный сторонник использования UIViewPropertyAnimator. Так много интересных функций, которые позволяют вам динамически модифицировать основные анимации.

Вот еще один пример добавления красной рамки во время встряхивания вида, а затем ее удаления по окончании встряхивания.

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

Использовать

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

Как пользоваться:

[UIView, UILabel, UITextField, UIButton & etc].layer.shake(NSTimeInterval(0.7))
3
Dmitriiy Mitrophanskiy
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])

}

// написать в базовом классе или любом контроллере вида и использовать его

1
Rana Ali Waseem

Это основано на CABasicAnimation, оно также содержит звуковой эффект:

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
Alessandro Ornano