iOS 分割輸入驗證碼的視覺效果

//自定義 view
@interface IDVertificationCodeInputView :UIView

/**背景圖片*/
@property (nonatomic,copy)NSString *backgroudImageName;
/**驗證碼/密碼的位數*/
@property (nonatomic,assign)NSInteger numberOfVertificationCode;
/**控制驗證碼/密碼是否密文顯示*/
@property (nonatomic,assign)bool secureTextEntry;
/**驗證碼/密碼內容,可以通過該屬性拿到驗證碼/密碼輸入框中驗證碼/密碼的內容*/
@property (nonatomic,copy)NSString *vertificationCode;

-(void)becomeFirstResponder;
@end

#import "IDVertificationCodeInputView.h"
#import "IDLabel.h"
@interface IDVertificationCodeInputView () <UITextFieldDelegate>

/**用於獲取鍵盤輸入的內容,實際不顯示*/
@property (nonatomic,strong)UITextField *textField;
/**驗證碼/密碼輸入框的背景圖片*/
@property (nonatomic,strong)UIImageView *backgroundImageView;
/**實際用於顯示驗證碼/密碼的label*/
@property (nonatomic,strong)IDLabel *label;

@end

@implementation IDVertificationCodeInputView

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [superinitWithFrame:frame]) {
        // 設置透明背景色,保證vertificationCodeInputView顯示的frame爲backgroundImageView的frame
        self.backgroundColor = [UIColorclearColor];
        // 設置驗證碼/密碼的位數默認爲四位
        self.numberOfVertificationCode =4;
        /* 調出鍵盤的textField */
        self.textField = [[UITextFieldalloc]initWithFrame:self.bounds];
        // 隱藏textField,通過點擊IDVertificationCodeInputView使其成爲第一響應者,來彈出鍵盤
        self.textField.hidden =YES;
        self.textField.keyboardType =UIKeyboardTypeNumberPad;
        self.textField.delegate =self;
        // 將textField放到最後邊
        [selfinsertSubview:self.textFieldatIndex:0];
        /* 添加用於顯示驗證碼/密碼的label */
        self.label = [[IDLabelalloc]initWithFrame:self.bounds];
        self.label.numberOfVertificationCode =self.numberOfVertificationCode;
        self.label.secureTextEntry =self.secureTextEntry;
        self.label.font =self.textField.font;
        [selfaddSubview:self.label];
    }
    returnself;
}
- (void)setBackgroudImageName:(NSString *)backgroudImageName {
    _backgroudImageName = backgroudImageName;
    // 若用戶設置了背景圖片,則添加背景圖片
    self.backgroundImageView = [[UIImageViewalloc]initWithFrame:self.bounds];
    self.backgroundImageView.image = [UIImageimageNamed:self.backgroudImageName];
    // 將背景圖片插入到label的後邊,避免遮擋驗證碼/密碼的顯示
    [selfinsertSubview:self.backgroundImageViewbelowSubview:self.label];
}
- (void)setNumberOfVertificationCode:(NSInteger)numberOfVertificationCode {
    _numberOfVertificationCode = numberOfVertificationCode;
    // 保持label的驗證碼/密碼位數與IDVertificationCodeInputView一致,此時label一定已經被創建
    self.label.numberOfVertificationCode =_numberOfVertificationCode;
}
- (void)setSecureTextEntry:(bool)secureTextEntry {
    _secureTextEntry = secureTextEntry;
    self.label.secureTextEntry =_secureTextEntry;
}
-(void)becomeFirstResponder{
    [self.textFieldbecomeFirstResponder];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self.textFieldbecomeFirstResponder];
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
 
   
    // 判斷是不是“刪除”字符
    if (string.length !=0) {//不是“刪除”字符
        // 判斷驗證碼/密碼的位數是否達到預定的位數
        if (textField.text.length <self.numberOfVertificationCode) {
            self.label.text = [textField.textstringByAppendingString:string];
            self.vertificationCode =self.label.text;
            if (self.label.text.length == self.numberOfVertificationCode) {
                 NSLog(@"tag 已經輸入完成驗證碼了vertificationCode= %@",_vertificationCode);
            }
            returnYES;
        } else {
            returnNO;
        }
    } else {//是“刪除”字符
        self.label.text = [textField.textsubstringToIndex:textField.text.length -1];
        self.vertificationCode =self.label.text;
        returnYES;
    }
}

@end
//自定義 uilabel

@interface IDLabel : UILabel

/**驗證碼/密碼的位數*/
@property (nonatomic,assign)NSInteger numberOfVertificationCode;
/**控制驗證碼/密碼是否密文顯示*/
@property (nonatomic,assign)bool secureTextEntry;

@end
#import "IDLabel.h"

@implementation IDLabel

//重寫setText方法,當text改變時手動調用drawRect方法,將text的內容按指定的格式繪製到label上
- (void)setText:(NSString *)text {
    [supersetText:text];
    // 手動調用drawRect方法
    [selfsetNeedsDisplay];
}

// 按照指定的格式繪製驗證碼/密碼
- (void)drawRect:(CGRect)rect1 {
    //計算每位驗證碼/密碼的所在區域的寬和高
    CGRect rect =CGRectMake(0,0,200,45);
    float width = rect.size.width / (float)self.numberOfVertificationCode;
    float height = rect.size.height;
    
    // 將每位驗證碼/密碼繪製到指定區域
    for (int i =0; i <self.text.length; i++) {
        // 計算每位驗證碼/密碼的繪製區域
        CGRect tempRect =CGRectMake(i * width,0, width, height);
        if (self.secureTextEntry) {//密碼,顯示圓點
            UIImage *dotImage = [UIImageimageNamed:@"dot"];
            // 計算圓點的繪製區域
            CGPoint securityDotDrawStartPoint =CGPointMake(width * i + (width - dotImage.size.width) /2.0, (tempRect.size.height - dotImage.size.height) / 2.0);
            // 繪製圓點
            [dotImage drawAtPoint:securityDotDrawStartPoint];
        } else {//驗證碼,顯示數字
            // 遍歷驗證碼/密碼的每個字符
            NSString *charecterString = [NSStringstringWithFormat:@"%c", [self.textcharacterAtIndex:i]];
            // 設置驗證碼/密碼的現實屬性
            NSMutableDictionary *attributes = [[NSMutableDictionaryalloc]init];
            attributes[NSFontAttributeName] =self.font;
            // 計算每位驗證碼/密碼的繪製起點(爲了使驗證碼/密碼位於tempRect的中部,不應該從tempRect的重點開始繪製)
            // 計算每位驗證碼/密碼的在指定樣式下的size
            CGSize characterSize = [charecterStringsizeWithAttributes:attributes];
            CGPoint vertificationCodeDrawStartPoint =CGPointMake(width * i + (width - characterSize.width) /2.0, (tempRect.size.height - characterSize.height) /2.0);
            // 繪製驗證碼/密碼
            [charecterString drawAtPoint:vertificationCodeDrawStartPointwithAttributes:attributes];
        }
    }
    //繪製底部橫線
    for (int k=0; k<self.numberOfVertificationCode; k++) {
        [selfdrawBottomLineWithRect:rectandIndex:k];
        [selfdrawSenterLineWithRect:rectandIndex:k];
    }

}

//繪製底部的線條
- (void)drawBottomLineWithRect:(CGRect)rect1 andIndex:(int)k{
    CGRect rect =CGRectMake(0,0,200,45);
    float width = rect.size.width / (float)self.numberOfVertificationCode;
    float height = rect.size.height;
    //1.獲取上下文
    CGContextRef context =UIGraphicsGetCurrentContext();
    //2.設置當前上下問路徑
    CGFloat lineHidth =0.25*ADAPTER_RATE;
    CGFloat strokHidth =0.5*ADAPTER_RATE;
    CGContextSetLineWidth(context, lineHidth);
    if ( k<=self.text.length ) {
        CGContextSetStrokeColorWithColor(context,HexRGB(0xEB3341).CGColor);
        CGContextSetFillColorWithColor(context,HexRGB(0xEB3341).CGColor);
    }else{
        CGContextSetStrokeColorWithColor(context,HexRGB(0xCCCCCD).CGColor);
        CGContextSetFillColorWithColor(context,HexRGB(0xCCCCCD).CGColor);
    }
    
    CGRect rectangle =CGRectMake(k*width+width/10,height-lineHidth-strokHidth,width-width/5,strokHidth);
    CGContextAddRect(context, rectangle);
    CGContextStrokePath(context);
}
//繪製中間的輸入的線條
- (void)drawSenterLineWithRect:(CGRect)rect1 andIndex:(int)k{
    if ( k==self.text.length ) {
        CGRect rect =CGRectMake(0,0,200,45);
        float width = rect.size.width / (float)self.numberOfVertificationCode;
        float height = rect.size.height;
        //1.獲取上下文
        CGContextRef context =UIGraphicsGetCurrentContext();
        CGContextSetLineWidth(context,0.5);
        CGContextSetStrokeColorWithColor(context,HexRGB(0xEB3341).CGColor);
        CGContextSetFillColorWithColor(context,HexRGB(0xEB3341).CGColor);
        CGContextMoveToPoint(context, width * k + (width -1.0) /2.0, height/5);
        CGContextAddLineToPoint(context,  width * k + (width -1.0) /2.0,height-height/5);
        CGContextStrokePath(context);
    }
}

@end

//調用方法
@interface TestViewController (){
    IDVertificationCodeInputView *vertificationCodeInputView;
}

@end

@implementation TestViewController

- (void)viewDidLoad {
    [superviewDidLoad];
    
    self.view.backgroundColor = [UIColorwhiteColor];
    vertificationCodeInputView = [[IDVertificationCodeInputViewalloc]initWithFrame:CGRectMake(50,250,200,45)];
    vertificationCodeInputView.backgroundColor =[UIColorwhiteColor];
    vertificationCodeInputView.backgroudImageName =@"clear_color_bg";
    // 驗證碼(顯示數字)
    vertificationCodeInputView.secureTextEntry =NO;
    [self.viewaddSubview:vertificationCodeInputView];
    [vertificationCodeInputViewbecomeFirstResponder];
   
}

- (void)didReceiveMemoryWarning {
    [superdidReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end


該方案是 參考網上 已有方案 改版成自己需要的特效 有需要的同學拿去用 



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章