animationUITextField指示一个错误的密码

我怎样才能添加一个animation到UITextField来表明错误的密码就像Facebook应用程序(在login屏幕)或Mac OS Xlogin框中的?

先谢谢你。

就是这样

 -(void)shake:(UIView *)theOneYouWannaShake { [UIView animateWithDuration:0.03 animations:^ { theOneYouWannaShake.transform = CGAffineTransformMakeTranslation(5*direction, 0); } completion:^(BOOL finished) { if(shakes >= 10) { theOneYouWannaShake.transform = CGAffineTransformIdentity; return; } shakes++; direction = direction * -1; [self shake:theOneYouWannaShake]; }]; } 

所以你需要三个东西:一个在震动前被设置为1的int方向被称为一个整数震动,在震动被调用之前被设置为0,并且一个常量MAX_SHAKES是一样大的。 希望有所帮助。

编辑:

这样称呼它:

  direction = 1; shakes = 0; [self shake:aUIView]; 

在头文件里面添加

 int direction; int shakes; 

(2015年1月16日)更新:(枚举UIViewAnimationOptions)强制转换罚款和UIViewAnimationOptionCurveEaseOut是2 <16每个UIView.h下typedef NS_OPTIONS(NSUInteger,UIViewAnimationOptions)

(2013年1月31日)进一步修改Kai的答案包括:

  1. 边缘延迟0.01s
  2. easeInOut
  3. 减less震动的持续时间从0.09到0.04
  4. 每隔1个完整的循环(右 – 左 – 右)通过pt节stream下降运动

注意:如果您计划一起摇动两个控件(电子邮件和密码),您可能希望避免使用类或静态variables进行摇动和翻译。 相反,初始化和通过摇,翻译为参数。 我使用静态,所以没有类variables需要。

 -(void)shakeAnimation:(UIView*) view { const int reset = 5; const int maxShakes = 6; //pass these as variables instead of statics or class variables if shaking two controls simultaneously static int shakes = 0; static int translate = reset; [UIView animateWithDuration:0.09-(shakes*.01) // reduce duration every shake from .09 to .04 delay:0.01f//edge wait delay options:(enum UIViewAnimationOptions) UIViewAnimationCurveEaseInOut animations:^{view.transform = CGAffineTransformMakeTranslation(translate, 0);} completion:^(BOOL finished){ if(shakes < maxShakes){ shakes++; //throttle down movement if (translate>0) translate--; //change direction translate*=-1; [self shakeAnimation:view]; } else { view.transform = CGAffineTransformIdentity; shakes = 0;//ready for next time translate = reset;//ready for next time return; } }]; } 

这个Swift 2.0的答案不需要recursion和循环。 只是利用CABasicAnimation通过改善这个SO回答 :

 func shakeView(shakeView: UIView) { let shake = CABasicAnimation(keyPath: "position") let xDelta = CGFloat(5) shake.duration = 0.15 shake.repeatCount = 2 shake.autoreverses = true let from_point = CGPointMake(shakeView.center.x - xDelta, shakeView.center.y) let from_value = NSValue(CGPoint: from_point) let to_point = CGPointMake(shakeView.center.x + xDelta, shakeView.center.y) let to_value = NSValue(CGPoint: to_point) shake.fromValue = from_value shake.toValue = to_value shake.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) shakeView.layer.addAnimation(shake, forKey: "position") } 

基于以前的答案作为快速方法准备使用:

 func shakeTextField (textField : UITextField, numberOfShakes : Int, direction: CGFloat, maxShakes : Int) { let interval : NSTimeInterval = 0.03 UIView.animateWithDuration(interval, animations: { () -> Void in textField.transform = CGAffineTransformMakeTranslation(5 * direction, 0) }, completion: { (aBool :Bool) -> Void in if (numberOfShakes >= maxShakes) { textField.transform = CGAffineTransformIdentity textField.becomeFirstResponder() return } self.shakeTextField(textField, numberOfShakes: numberOfShakes + 1, direction: direction * -1, maxShakes: ) }) } 

调用它:

 shakeTextField(aTextField,numberOfShakes:0, direction :1, maxShakes : 10) 

如果你来这里寻找一个MonoTouch的答案,这里是Dickey代码的粗略翻译:

 public static void /*Harlem*/Shake (this UIView view, int shakes = 6, int translation = 5) { UIView.Animate (0.03 + (shakes * 0.01), 0.01, UIViewAnimationOptions.CurveEaseInOut, () => { view.Transform = CGAffineTransform.MakeTranslation (translation, 0); }, () => { if (shakes == 0) { view.Transform = CGAffineTransform.MakeIdentity (); return; } if (translation > 0) translation --; translation *= -1; shakes --; Shake (view, shakes, translation); }); } 

把它放在你的扩展方法的其余部分,像这样调用:

 password.Shake (); 

这是我的旋转:

 @implementation UITextField (Shake) - (void)shake { [self shakeWithIterations:0 direction:1 size:4]; } #pragma mark - Private - (void)shakeWithIterations:(int)iterations direction:(int)direction size:(int)size { [UIView animateWithDuration:0.09-(iterations*.01) animations:^{ self.transform = CGAffineTransformMakeTranslation(size*direction, 0); } completion:^(BOOL finished) { if (iterations >= 5 || size <= 0) { self.transform = CGAffineTransformIdentity; return; } [self shakeWithIterations:iterations+1 direction:direction*-1 size:MAX(0, size-1)]; }]; } @end 

我试过@stefreak解决scheme,但循环的方法不适用于iOS 7.1。 所以我把@stefreak和@Chris的解决scheme结合在一起,并添加了完成块,在抖动结束时通知。 这是我的代码:

 - (void)shakeView:(UIView *)view iterations:(NSInteger)iterations direction:(NSInteger)direction completion:(void (^)())completion { const NSInteger MAX_SHAKES = 6; const CGFloat SHAKE_DURATION = 0.05; const CGFloat SHAKE_TRANSFORM = 10.0; [UIView animateWithDuration:SHAKE_DURATION delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{ view.transform = iterations >= MAX_SHAKES ? CGAffineTransformIdentity : CGAffineTransformMakeTranslation(SHAKE_TRANSFORM * direction, 0); } completion:^(BOOL finished) { if (finished) { if (iterations >= MAX_SHAKES) { if (completion) { completion(); } } else { [self shakeView:view iterations:(iterations + 1) direction:(direction * -1) completion:completion]; } } }]; } - (void)shakeView:(UIView *)view completion:(void (^)())completion { [self shakeView:view iterations:0 direction:1 completion:completion]; } 

iOS iPhone文本框密码窗口视图晃动

我为UIView创build了一个类别方法,可以用来震动任何元素,例如UITextField,并且能够在震动结束后得到通知。 以下是如何使用它:

 [myPasswordField shake]; // Or with a callback after the shake [myPasswordField shakeWithCallback:^{ NSLog(@"Shaking has ended"); }]; 

这是代码。

UIView的+ Shake.h

 #import <UIKit/UIKit.h> @interface UIView (UIView_Shake) -(void)shake; -(void)shakeWithCallback:(void (^)(void))completeBlock; @end 

UIView的+ Shake.m

 #import "UIView+Shake.h" #import <objc/runtime.h> @implementation UIView (UIView_Shake) static void *NumCurrentShakesKey; static void *NumTotalShakesKey; static void *ShakeDirectionKey; - (int)numCurrentShakes { return [objc_getAssociatedObject(self, &NumCurrentShakesKey) intValue]; } - (void)setNumCurrentShakes:(int)value { objc_setAssociatedObject(self, &NumCurrentShakesKey, [NSNumber numberWithInt:value], OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (int)numTotalShakes { return [objc_getAssociatedObject(self, &NumTotalShakesKey) intValue]; } - (void)setNumTotalShakes:(int)value { objc_setAssociatedObject(self, &NumTotalShakesKey, [NSNumber numberWithInt:value], OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (int)shakeDirection { return [objc_getAssociatedObject(self, &ShakeDirectionKey) intValue]; } - (void)setShakeDirection:(int)value { objc_setAssociatedObject(self, &ShakeDirectionKey, [NSNumber numberWithInt:value], OBJC_ASSOCIATION_RETAIN_NONATOMIC); } -(void)shake { [self shakeNextWithCompleteBlock:nil]; } -(void)shakeWithCallback:(void (^)(void))completeBlock { self.numCurrentShakes = 0; self.numTotalShakes = 6; self.shakeDirection = 8; [self shakeNextWithCompleteBlock:completeBlock]; } -(void)shakeNextWithCompleteBlock:(void (^)(void))completeBlock { UIView* viewToShake = self; [UIView animateWithDuration:0.08 animations:^ { viewToShake.transform = CGAffineTransformMakeTranslation(self.shakeDirection, 0); } completion:^(BOOL finished) { if(self.numCurrentShakes >= self.numTotalShakes) { viewToShake.transform = CGAffineTransformIdentity; if(completeBlock != nil) { completeBlock(); } return; } self.numCurrentShakes++; self.shakeDirection = self.shakeDirection * -1; [self shakeNextWithCompleteBlock:completeBlock]; }]; } @end 

你也可以使用基本的animation

 let animation = CABasicAnimation(keyPath: "position") animation.duration = 0.09 animation.repeatCount = 4 animation.autoreverses = true animation.fromValue = NSValue(CGPoint: CGPointMake(txtField.center.x - 10, txtField.center.y)) animation.toValue = NSValue(CGPoint: CGPointMake(txtField.center.x + 10, txtField.center.y)) txtField.layer.addAnimation(animation, forKey: "position") 

在这里你可以改变durationrepeatCount 。改变fromValuefromValue会改变在震动中移动的距离

这里有一个Swift库,用于在github中为Textfield设置animation。 只需导入swift文件并执行如下

 // Shake with the default speed self.textField.shake(10, delta:5) //10 no. of shakes with 5 points wide // Shake with a custom speed self.sampleText.shake(10, delta: 5, speed: 0.10) //10 no. of shakes with 5 points wide in 100ms per shake 

Swift 3和stack_view已经创build了textField

 func shakeTextField (stack_view : UIStackView, numberOfShakes : Int, direction: CGFloat, maxShakes : Int) { let interval : TimeInterval = 0.05 UIView.animate(withDuration: interval, animations: { () -> Void in stack_view.transform = CGAffineTransform(translationX: 5 * direction, y: 0) }, completion: { (aBool :Bool) -> Void in if (numberOfShakes >= maxShakes) { stack_view.becomeFirstResponder() return } self.shakeTextField(stack_view: stack_view, numberOfShakes: numberOfShakes + 1, direction: direction * -1, maxShakes: maxShakes ) }) }