美文网首页iOS Developer
一个简单的获取验证码控件的封装

一个简单的获取验证码控件的封装

作者: 浪漫恋星空 | 来源:发表于2017-04-10 17:40 被阅读163次

    写在前面

    在日常的开发过程中,获取验证码是一个常见的功能。一般情况下,为了提高用户体验,产品都会在点击获取验证码之后,让这个点击控件做一个渐变动画,设置一个时长,然后可以点击重新获取。这是一个非常简单且经常用到的功能,可以考虑将这个小控件直接封装出来,方便随时使用。

    实现效果

    效果.gif

    实现思路

    自定义一个UIView,在这个View上添加一个显示进度的ProgressView,和一个显示文字的UILabel。通过NSTimer修改UILabel上的文字,渐变的动画就是简单的UIView动画,通过改变ProgressView的frame来实现。

    实现代码

    创建一个XKCaptchaView继承于UIView,在.h头文件中声明需要的属性和方法。

    #import <UIKit/UIKit.h>
    
    @class XKCaptchaView;
    
    // 点击XKCaptchaView触发的回调Block
    typedef void(^XKCaptchaActionBlock)(XKCaptchaView *view);
    
    @interface XKCaptchaView : UIView
    
    // 间隔时长(指定一个时长,在这个时长之后控件可以重新点击)
    @property (nonatomic, assign) NSTimeInterval reEnableTimeInterval;
    
    // 进度视图的背景颜色
    @property (nonatomic, strong) UIColor *progressViewBgColor;
    
    // 初始化方法
    - (instancetype)initWithFrame:(CGRect)frame reEnableTimeInterval:(NSTimeInterval)interval actionBlock:(XKCaptchaActionBlock)actionBlock;
    
    // 开始动画
    - (void)startAnimation;
    
    // 回到最初的状态
    - (void)changToNormal;
    
    @end
    

    实现文件的代码如下:

    #import "XKCaptchaView.h"
    
    @implementation XKCaptchaView {
        
        UIView *_reEnableProgressView;
        
        UILabel *_titleLabel;
        
        XKCaptchaActionBlock _actionBlock;
        
        NSTimer *_timer;
        
        NSInteger _timerInteger;
    }
    
    - (void)dealloc {
        
        [_timer invalidate];
        
        _timer = nil;
        
        [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
    }
    
    - (instancetype)initWithFrame:(CGRect)frame reEnableTimeInterval:(NSTimeInterval)interval actionBlock:(XKCaptchaActionBlock)actionBlock {
        
        if (self = [super initWithFrame:frame]) {
            
            _reEnableTimeInterval = interval;
            
            _reEnableProgressView = [[UIView alloc] initWithFrame:self.bounds];
            
            self.backgroundColor = [UIColor lightGrayColor];
            
            _reEnableProgressView.backgroundColor = [UIColor orangeColor];
            
            if (actionBlock) {
                _actionBlock = actionBlock;
            }
            
            UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap)];
            
            [self addGestureRecognizer:tap];
            
            [self addSubview:_reEnableProgressView];
            
            _titleLabel = [[UILabel alloc] initWithFrame:self.bounds];
            
            _titleLabel.text = @"获取验证码";
            
            _titleLabel.textAlignment = NSTextAlignmentCenter;
            
            _titleLabel.textColor = [UIColor whiteColor];
            
            _timerInteger = interval;
            
            [self addSubview:_titleLabel];
        }
        
        return self;
    }
    
    - (void)handleTap {
        
        if (_actionBlock) {
         
            _actionBlock(self);
        }
    }
    
    - (void)change {
        
        if (_timerInteger == 0) {
            
            [_timer invalidate];
            
            _titleLabel.text = @"获取验证码";
            
            _timerInteger = _reEnableTimeInterval;
            
            return;
        }
        
        _timerInteger--;
        
        _titleLabel.text = [NSString stringWithFormat:@"获取验证码(%ld)",(long)_timerInteger];
    }
    
    - (void)startAnimation {
        
        _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(change) userInfo:nil repeats:YES];
        
        [_timer fire];
        
        self.userInteractionEnabled = NO;
        
        _reEnableProgressView.frame = CGRectMake(0, 0, 0, _reEnableProgressView.frame.size.height);
        
        [UIView animateWithDuration:_reEnableTimeInterval animations:^{
            
            _reEnableProgressView.frame = self.bounds;
            
        } completion:^(BOOL finished) {
            
            self.userInteractionEnabled = YES;
        }];
    }
    
    - (void)changToNormal {
        
        [_timer invalidate];
        
        _timerInteger = _reEnableTimeInterval;
        
        [_reEnableProgressView.layer removeAllAnimations];
        
        _titleLabel.text = @"获取验证码";
    }
    
    - (void)setProgressViewBgColor:(UIColor *)progressViewBgColor {
        
        _progressViewBgColor = progressViewBgColor;
        
        _reEnableProgressView.backgroundColor = progressViewBgColor;
    }
    
    @end
    

    平时写代码有一个坏习惯,就是实现文件不喜欢写注释。这里简单解释一下上面的代码,在初始化方法中向XKCaptchaView添加了reEnableProgressView进度View,显示文字的titleLabel,并且初始化了一些默认的配置信息。向XKCaptchaView添加了单击手势,用来接收处理点击事件。最主要的方法就是- (void)startAnimation这个方法,在这个方法中,初始化了定时器,开始动画之后,XKCaptchaView便不再响应用户操作,直到动画完成,或者手动调用- (void)changToNormal方法。设置reEnableProgressViewframe,然后根据reEnableTimeInterval改变其宽度。定时器每秒执行一次- (void)change方法,在这个方法中改变titleLabel上的文字,当timerInteger为0时,停止定时器,还原titleLabel- (void)changToNormal该方法是用来还原整个控件的状态的,需要手动调用。这个方法存在的意义是,点击控件发起网络请求去获取验证码,验证码获取成功了之后,reEnableProgressView就没有继续做动画的必要了。所以这里提供这样一个方法。- (void)changToNormal里面也都是简单的操作,首先停止定时器,重新将reEnableTimeInterval赋值给timerInteger,移除reEnableProgressView的动画,还原titleLabel。这里不用将XKCaptchaViewuserInteractionEnabled设置为YES。因为在移除reEnableProgressView动画的时候,会执行UIView动画的completion回调。最终,我们就实现了这样一个简单的需求。

    简单的使用

    在控制器中简单使用自定义的XKCaptchaView测试一下看看是否满足需求。

    #import "ViewController.h"
    #import "XKCaptchaView.h"
    
    @interface ViewController ()
    
    @property (nonatomic, strong) XKCaptchaView *captchaView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        
        [super viewDidLoad];
        
        [self.view addSubview:self.captchaView];
    }
    
    - (XKCaptchaView *)captchaView {
        
        if (!_captchaView) {
            
            _captchaView = [[XKCaptchaView alloc] initWithFrame:CGRectMake(0, 0, 150, 30) reEnableTimeInterval:60 actionBlock:^(XKCaptchaView *view) {
                
                [view startAnimation];
                
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    
                    [[[UIAlertView alloc] initWithTitle:@"温馨提示" message:@"验证码获取成功" delegate:nil cancelButtonTitle:@"我知道了" otherButtonTitles:nil, nil] show];
                    
                    [self.captchaView changToNormal];
                    
                });
                
            }];
            
            _captchaView.center = self.view.center;
        }
        return _captchaView;
    }
    @end
    

    最终的效果如图

    最终效果图.gif
    这就是一个简单获取验证码控件的封装,虽然功能简单,但是该有的都有。全部的代码都已经贴出来了。如果你没有时间阅读源码而你又需要这个小控件的话 传送门在这里
    如果你在阅读或者使用的过程中发现错误或者有什么更好的建议,欢迎留言指出。

    相关文章

      网友评论

        本文标题:一个简单的获取验证码控件的封装

        本文链接:https://www.haomeiwen.com/subject/kgisattx.html