我怎么可以添加动画到UITextField
指示错误的密码完全一样,在Facebook的应用程序(在登录屏幕)或Mac OS X的登录框?
先感谢您。
我怎么可以添加动画到UITextField
指示错误的密码完全一样,在Facebook的应用程序(在登录屏幕)或Mac OS X的登录框?
先感谢您。
类似的东西
-(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方向称为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日)进一步修改凯的答案,包括:
注意:如果你打算在抖两个控件(电子邮件和密码)在一起,你可能希望避免使用类或静态变量抖动和平移。 相反,初始化并通过抖动和平移作为参数。 我用静态所以没有类变量需要。
-(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;
}
}];
}
这雨燕2.0的答案不需要递归和没有循环。 只需利用CABasicAnimation
通过细化这个苏答案 :
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")
}
更新了斯威夫特4:
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 = CGPoint(x: shakeView.center.x - xDelta, y: shakeView.center.y)
let from_value = NSValue(cgPoint: from_point)
let to_point = CGPoint(x: shakeView.center.x + xDelta, y: 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.add(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解决方案,但在循环方法并不在iOS 7.1的工作。 所以我结合从@stefreak和@克里斯的解决方案,并添加完成块当震动结束通知。 这里是我的代码:
- (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];
}
我创建的UIView类别方法可以用来动摇的任何元素 - 例如为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
你也可以做到这一点使用基本动画
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")
在这里,您可以更改duration
, repeatCount
.Changing到fromValue
和toValue
将改变距离,摇移
由于问题是关于Objective-C的,由于我在我的项目使用Objective-C,我觉得这种Objective-C的翻译此之前的雨燕答案可能是别人有用:
- (void)shakeView:(UIView*)view
{
CABasicAnimation *shake = [CABasicAnimation animationWithKeyPath:@"position"];
CGFloat xDelta = 5.0;
shake.duration = 0.15;
shake.repeatCount = 2;
shake.autoreverses = YES;
CGPoint fromPoint = CGPointMake(view.center.x - xDelta, view.center.y);
CGPoint toPoint = CGPointMake(view.center.x + xDelta, view.center.y);
shake.fromValue = [NSValue valueWithCGPoint:fromPoint];
shake.toValue = [NSValue valueWithCGPoint:toPoint];
shake.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[view.layer addAnimation:shake forKey:@"position"];
}
有一个斯威夫特库在github上动画文本字段这里 。 简单地导入迅速文件,如下实施
// 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
斯威夫特3和stack_view instaed文本框
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 )
})
}