IOS登录界面验证失败的抖动特效

来源:互联网 发布:北京中搜网络是真是假 编辑:程序博客网 时间:2024/05/16 10:48
登录验证失败的抖动特效


此案例采用storyboard布局方式,Xcode7.3默认配置。
1.storyboard布局。
首先在左侧的项目导航窗口打开Assets.xcassets,在该文件编辑窗口左侧窗右击鼠标选择App Icons & Launch Images菜单,选择子菜单New IOS Launch Image。

然后打开项目文件General选项卡,下拉到App Icons and Launch Images项,清空Launch Screen  File表单内容。将App Icons Source 选择 Use  Asset Catalog项。保存后切换到Main.storyboard文件,command + option + 1 去掉Interface Builder Document栏Use Size Classes复选前面的勾。随后,拖拽2个textField、2个View 、三个button到ViewController里,依次调整属性面板属性,布局如下:(技巧:view控件的高度设置为1就是下划线,密码控件勾选secure  text entry)


2.编写代码
新建AFViewShaker类,继承NSObject类。
.h和.m文件内容分别如下:


AFViewShaker.h


#import <UIKit/UIKit.h>
@interface AFViewShaker : NSObject
- (instancetype)initWithView:(UIView *)view;
- (instancetype)initWithViewsArray:(NSArray *)viewsArray;


- (void)shake;
- (void)shakeWithDuration:(NSTimeInterval)duration completion:(void (^)())completion;
@end


AFViewShaker.m


#import "AFViewShaker.h"
static NSTimeInterval const kAFViewShakerDefaultDuration = 0.5;
static NSString * const kAFViewShakerAnimationKey = @"kAFViewShakerAnimationKey";


@interface AFViewShaker ()
@property (nonatomic, strong) NSArray * views;
@property (nonatomic, assign) NSUInteger completedAnimations;
@property (nonatomic, copy) void (^completionBlock)();
@end


@implementation AFViewShaker
- (instancetype)initWithView:(UIView *)view {
    return [self initWithViewsArray:@[ view ]];
}


- (instancetype)initWithViewsArray:(NSArray *)viewsArray {
    self = [super init];
    if ( self ) {
        self.views = viewsArray;
    }
    return self;
}


#pragma mark - Public methods


- (void)shake {
    [self shakeWithDuration:kAFViewShakerDefaultDuration completion:nil];
}


- (void)shakeWithDuration:(NSTimeInterval)duration completion:(void (^)())completion {
    self.completionBlock = completion;
    for (UIView * view in self.views) {
        [self addShakeAnimationForView:view withDuration:duration];
    }
}


#pragma mark - Shake Animation
- (void)addShakeAnimationForView:(UIView *)view withDuration:(NSTimeInterval)duration {
    CAKeyframeAnimation * animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.x"];
    CGFloat currentTx = view.transform.tx;
    
    animation.delegate = self;
    animation.duration = duration;
    animation.values = @[ @(currentTx), @(currentTx + 15), @(currentTx-12), @(currentTx + 9), @(currentTx -6), @(currentTx + 6), @(currentTx) ];
    animation.keyTimes = @[ @(0), @(0.225), @(0.425), @(0.6), @(0.75), @(0.875), @(1) ];
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    [view.layer addAnimation:animation forKey:kAFViewShakerAnimationKey];
}


#pragma mark - CAAnimation Delegate
- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag {
    self.completedAnimations += 1;
    if ( self.completedAnimations >= self.views.count ) {
        self.completedAnimations = 0;
        if ( self.completionBlock ) {
            self.completionBlock();
        }
    }
}
@end

 然后编辑ViewController.m文件,内容如下:

#import "ViewController.h"
#import "AFViewShaker.h"
@interface ViewController ()
@property (nonatomic, strong) IBOutletCollection(UIView) NSArray * allTextFields;
@property (nonatomic, strong) IBOutletCollection(UIButton) NSArray * allButtons;
@property (nonatomic, strong) AFViewShaker * viewShaker;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.viewShaker = [[AFViewShaker alloc] initWithViewsArray:self.allTextFields];
    
    for (UIButton * button in self.allButtons) {
        button.layer.borderColor = [[UIColor orangeColor] CGColor];
        button.layer.borderWidth = 1;
        button.layer.cornerRadius = 5;
    }
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
#pragma mark - Actions

- (IBAction)onShakeOneAction:(UIButton *)sender {
    [[[AFViewShaker alloc] initWithView:self.allButtons[0]] shake];
}


- (IBAction)onShakeAllAction:(UIButton *)sender {
    [self.viewShaker shake];
}


- (IBAction)onShakeAllWithBlockAction:(UIButton *)sender {
    [self.viewShaker shakeWithDuration:0.6 completion:^{
        //[[[UIAlertView alloc] initWithTitle:@"Hello" message:@"This is completions block"  delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
        UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"This is completions block" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction * isOK = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:isOK];
        [self presentViewController:alert animated:YES  completion:nil];
        
    }];
}
-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event{
    //NSLog(@"%@s",_allTextFields);
    for (int i = 0; i < [_allTextFields count]; i++) {
        //NSLog(@"%@",[[_allTextFields objectAtIndex:i] class]);
        if([[_allTextFields objectAtIndex:i] isKindOfClass: [UIView class]]){
            [_allTextFields[i] resignFirstResponder];
        }
    }
}

3.建立代码与控件的关联
接着打开storyboard,进入助手编辑模式,建立控件和代码间的关系。将三个按钮,依次、分别按住Ctrl连上IBAction方法上。然后将textField控件、view控件一个一个连接在@property (nonatomic, strong) IBOutletCollection(UIView) NSArray * allTextFields;上,将三个按钮挨个连在@property (nonatomic, strong) IBOutletCollection(UIButton) NSArray * allButtons;上,command + R运行即可!效果如下:



点按钮试试!不错的抖动效果哦!偷笑

0 0