密码输入框

https://gitee.com/cityleaf/LYPaymentField

 

//

//  LYSecurityField.h

//  PaymentSecurityField

//

//  Created by 刘宇 on 2017/8/2.

//  Copyright © 2017年 刘宇. All rights reserved.

//

 

#import

 

NS_ASSUME_NONNULL_BEGIN

 

typedef NS_ENUM(NSUInteger, SecurityCharacterType) {

    SecurityCharacterTypeSecurityDot,   ///

    SecurityCharacterTypePlainText,     ///

    SecurityCharacterTypeCustomImage,   ///

    SecurityCharacterTypeHorizontalLine,///

};

 

typedef NS_ENUM(NSUInteger, BorderType) {

    BorderTypeHaveRoundedCorner,///

    BorderTypeNoRoundedCorner,  ///

    BorderTypeSeparateBox,      ///

    BorderTypeNoBorder,         ///

};

 

@class LYSecurityField;

@protocol LYPaymentFieldDelegate

 

@required

 

/**

输入完成 end editing

 

@param paymentField 支付框

*/

- (void)lYPaymentFieldDidFinishedEditing:(LYSecurityField *)paymentField;

 

@optional

 

/**

开始输入 begin editing

 

@param paymentField 支付框

*/

- (void)lYPaymentFieldDidBeginEditing:(LYSecurityField *)paymentField;

 

/**

删除一个字符 delete a character

 

@param paymentField 支付框

*/

- (void)lYPaymentFieldDidDelete:(LYSecurityField *)paymentField;

 

/**

清除完成 clear all characters

 

@param paymentField 支付框

*/

- (void)lYPaymentFieldDidClear:(LYSecurityField *)paymentField;

 

@end

 

@interface LYSecurityField : UIControl

 

@property (nonatomic, assign) id delegate;

@property (nonatomic, assign) NSInteger numberOfCharacters;

@property (nonatomic, assign) SecurityCharacterType securityCharacterType;

@property (nonatomic, assign) BorderType borderType;

@property (nonatomic, assign) CGFloat diameterOfDot;

@property (nonatomic, assign) CGSize securityImageSize;

@property (nonatomic, assign, readonly) NSInteger countOfVerification;

 

@property (nonatomic, copy) NSString *text;

@property (nonatomic, copy) void (^completion)(LYSecurityField *field, NSString *text);

 

@property (nonatomic, strong) UIColor *tintColor;

@property (nonatomic, strong) UIColor *colorOfCharacter;

@property (nonatomic, strong) UIImage *securityImage;

 

- (instancetype)initWithNumberOfCharacters:(NSInteger)numberOfCharacters

                     securityCharacterType:(SecurityCharacterType)securityCharacterType

                                borderType:(BorderType)borderType;

 

- (void)clear;

 

@end

 

NS_ASSUME_NONNULL_END

 

 

 

//

//  LYSecurityField.m

//  PaymentSecurityField

//

//  Created by 刘宇 on 2017/8/2.

//  Copyright © 2017年 刘宇. All rights reserved.

//

 

#import "LYSecurityField.h"

 

NS_ASSUME_NONNULL_BEGIN

 

#define DEFAULT_COUNT_CHARACTERS 6;

#define DEFAULT_RADIUS 6;

#define DEFAULT_BODER_WIDTH 0.5;

#define DEFAULT_HORIZONTALLINE_WIDTH 20

#define DEFAULT_CUSTOMIMAGE_WIDTH 20

 

void *KVOFrameContext;

 

@interface LYSecurityField()

{

    int completion_count;

}

 

@property (nonatomic, strong) UIView *contentView;

@property (nonatomic, strong) NSMutableArray *lines;

@property (nonatomic, strong) NSMutableArray *boxs;

/**

An array of layers holding secure placeholders.

*/

@property (nonatomic, strong) NSMutableArray *dots;

@property (nonatomic, strong) NSMutableArray *plaintexts;

@property (nonatomic, strong) NSMutableArray *horizontalLines;

@property (nonatomic, strong) NSMutableArray *customImages;

@property (nonatomic, strong) NSMutableDictionary *placeholderDic;

 

- (CAShapeLayer *)createSecurityDot;

- (CALayer *)createSeparaterLine;

- (CATextLayer *)createCharacter;

- (CALayer *)createCustomImage;

- (CALayer *)createHorizontalLine;

 

@end

 

@implementation LYSecurityField

 

- (void)dealloc

{

    [self removeObserver:self forKeyPath:@"frame" context:KVOFrameContext];

}

 

- (instancetype)initWithNumberOfCharacters:(NSInteger)numberOfCharacters securityCharacterType:(SecurityCharacterType)securityCharacterType borderType:(BorderType)borderType

{

    self = [super init];

    if (self) {

        [self steup];

        self.numberOfCharacters = numberOfCharacters;

        self.securityCharacterType = securityCharacterType;

        self.borderType = borderType;

    }

    return self;

}

 

- (instancetype)init

{

    self = [super init];

    if (self) {

        [self steup];

    }

    return self;

}

 

- (void)steup

{

    self.contentView = ({

        UIView *contentView = [[UIView alloc] init];

        contentView.backgroundColor = UIColor.clearColor;

        contentView.userInteractionEnabled = NO;

        contentView;

    });

    [self addSubview:self.contentView];

    self.diameterOfDot = 15;

    self.colorOfCharacter = UIColor.blackColor;

    self.text = @"";

    self.placeholderDic = [NSMutableDictionary dictionary];

    self.lines = [NSMutableArray array];

    [self addTarget:self action:@selector(hangdleAction:) forControlEvents:UIControlEventTouchUpInside];

    [self addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:KVOFrameContext];

}

 

- (void)layoutSubviews

{

    [super layoutSubviews];

    

    self.contentView.frame = self.bounds;

    

    CGFloat width = CGRectGetWidth(self.frame);

    CGFloat height = CGRectGetHeight(self.frame);

    CGFloat pieceWidth = width / self.numberOfCharacters;

    

    !self.placeholderDic[@(self.securityCharacterType)]?:[self.placeholderDic[@(self.securityCharacterType)] enumerateObjectsUsingBlock:^(CALayer *  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

        obj.position = CGPointMake(pieceWidth / 2.f + (pieceWidth * idx), height / 2.f);

    }];

    

    if (self.borderType != BorderTypeNoBorder) {

        [self.lines enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

            [self.contentView.layer addSublayer:obj];

            obj.frame = CGRectMake(pieceWidth * (idx + 1) - self.layer.borderWidth / 2.f, 0, self.layer.borderWidth, height);

        }];

    }

}

 

#pragma mark - createPlaceholderCharacter

 

/**

Create a black dot.

 

@return dot

*/

- (CAShapeLayer *)createSecurityDot

{

    CAShapeLayer *layer = [[CAShapeLayer alloc] init];

    layer.bounds = CGRectMake(0, 0, self.diameterOfDot, self.diameterOfDot);

    layer.path = [UIBezierPath bezierPathWithRoundedRect:layer.bounds cornerRadius:self.diameterOfDot / 2.f].CGPath;

    layer.opacity = 0;

    [self.contentView.layer addSublayer:layer];

    return layer;

}

 

/**

Create a split line.

 

@return line

*/

- (CALayer *)createSeparaterLine

{

    CALayer *layer = [[CALayer alloc] init];

    layer.backgroundColor = self.tintColor.CGColor?:self.layer.borderColor;

    return layer;

}

 

/**

Create an unencrypted character.

 

@return character

*/

- (CATextLayer *)createCharacter

{

    CATextLayer *layer = [[CATextLayer alloc] init];

    layer.bounds = CGRectMake(0, 0, self.diameterOfDot*3, self.diameterOfDot*3);

    layer.foregroundColor = UIColor.blackColor.CGColor;

    layer.contentsScale = [UIScreen mainScreen].scale;

    layer.alignmentMode = kCAAlignmentCenter;

    layer.wrapped = YES;

    layer.opacity = 0;

    [self.contentView.layer addSublayer:layer];

    return layer;

}

 

/**

Customize a picture that represents security.

 

@return layer

*/

- (CALayer *)createCustomImage

{

    CALayer *layer = [[CALayer alloc] init];

    layer.opacity = 0;

    [self.contentView.layer addSublayer:layer];

    return layer;

}

 

- (CALayer *)createHorizontalLine

{

    CALayer *layer = [[CALayer alloc] init];

    layer.bounds = CGRectMake(0, 0, DEFAULT_HORIZONTALLINE_WIDTH, 5);

    layer.backgroundColor = UIColor.blackColor.CGColor;

    layer.opacity = 0;

    [self.contentView.layer addSublayer:layer];

    return layer;

}

 

#pragma mark - set

 

- (void)setNumberOfCharacters:(NSInteger)numberOfCharacters

{

    if (numberOfCharacters != _numberOfCharacters) {

        _numberOfCharacters = numberOfCharacters;

        for (int i = 0; i < self.numberOfCharacters-1; i++) {

            [self.lines addObject:[self createSeparaterLine]];

        }

    }

}

 

- (void)setDiameterOfDot:(CGFloat)diameterOfDot

{

    _diameterOfDot = diameterOfDot;

    if (self.placeholderDic[@(SecurityCharacterTypeSecurityDot)]) {

        [self.dots enumerateObjectsUsingBlock:^(CAShapeLayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

            obj.bounds = CGRectMake(0, 0, diameterOfDot, diameterOfDot);

            obj.path = [UIBezierPath bezierPathWithRoundedRect:obj.bounds cornerRadius:diameterOfDot / 2.f].CGPath;

        }];

    }

    

}

 

- (void)setSecurityImage:(UIImage *)securityImage

{

    _securityImage = securityImage;

    !self.placeholderDic[@(self.securityCharacterType)]?:[self.placeholderDic[@(self.securityCharacterType)] enumerateObjectsUsingBlock:^(CALayer * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

        obj.contents = (id)securityImage.CGImage;

    }];

}

 

- (void)setTintColor:(UIColor *)tintColor

{

    _tintColor = tintColor;

    self.layer.borderColor = tintColor.CGColor;

}

 

- (void)setColorOfCharacter:(UIColor *)colorOfCharacter

{

    _colorOfCharacter = colorOfCharacter;

    

    if (self.securityCharacterType == SecurityCharacterTypeSecurityDot) {

        [self.placeholderDic[@(self.securityCharacterType)] enumerateObjectsUsingBlock:^(CAShapeLayer   * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

            obj.strokeColor = colorOfCharacter.CGColor;

        }];

    } else if (self.securityCharacterType == SecurityCharacterTypePlainText) {

        [self.placeholderDic[@(self.securityCharacterType)] enumerateObjectsUsingBlock:^(CATextLayer   * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

            obj.foregroundColor = colorOfCharacter.CGColor;

        }];

    } else if (self.securityCharacterType == SecurityCharacterTypeHorizontalLine) {

        [self.placeholderDic[@(self.securityCharacterType)] enumerateObjectsUsingBlock:^(CATextLayer   * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

            obj.backgroundColor = colorOfCharacter.CGColor;

        }];

    }

}

 

- (void)setSecurityCharacterType:(SecurityCharacterType)securityCharacterType

{

    _securityCharacterType = securityCharacterType;

    

    if (!self.placeholderDic[@(securityCharacterType)]) {

        if (securityCharacterType == SecurityCharacterTypeSecurityDot) {

            self.placeholderDic[@(securityCharacterType)] = self.dots;

        } else if (securityCharacterType == SecurityCharacterTypePlainText) {

            self.placeholderDic[@(securityCharacterType)] = self.plaintexts;

        } else if (securityCharacterType == SecurityCharacterTypeCustomImage) {

            self.placeholderDic[@(securityCharacterType)] = self.customImages;

        } else if (securityCharacterType == SecurityCharacterTypeHorizontalLine) {

            self.placeholderDic[@(securityCharacterType)] = self.horizontalLines;

        }

    }

}

 

- (void)setBorderType:(BorderType)borderType

{

    _borderType = borderType;

    

    switch (borderType) {

        case BorderTypeHaveRoundedCorner:

        {

            self.layer.borderColor = self.tintColor.CGColor;

            self.layer.borderWidth = DEFAULT_BODER_WIDTH;

            self.layer.cornerRadius = DEFAULT_RADIUS;

            break;

        }

        case BorderTypeNoRoundedCorner:

        {

            self.layer.borderColor = self.tintColor.CGColor;

            self.layer.borderWidth = DEFAULT_BODER_WIDTH;

            self.layer.cornerRadius = 0;

            break;

        }

        case BorderTypeNoBorder:

        {

            self.layer.borderWidth = 0;

            break;

        }

        default:

            break;

    }

}

 

#pragma mark - get

 

- (NSInteger)countOfVerification

{

    return completion_count;

}

 

- (NSMutableArray *)dots

{

    if (!_dots) {

        _dots = [NSMutableArray array];

        for (int i = 0; i < self.numberOfCharacters; i++) {

            [_dots addObject:[self createSecurityDot]];

        }

    }

    return _dots;

}

 

- (NSMutableArray *)plaintexts

{

    if (!_plaintexts) {

        _plaintexts = [NSMutableArray array];

        for (int i = 0; i < self.numberOfCharacters; i++) {

            [_plaintexts addObject:[self createCharacter]];

        }

    }

    return _plaintexts;

}

 

- (NSMutableArray *)horizontalLines

{

    if (!_horizontalLines) {

        _horizontalLines = [NSMutableArray array];

        for (int i = 0; i < self.numberOfCharacters; i++) {

            [_horizontalLines addObject:[self createHorizontalLine]];

        }

    }

    return _horizontalLines;

}

 

- (NSMutableArray *)customImages

{

    if (!_customImages) {

        _customImages = [NSMutableArray array];

        for (int i = 0; i < self.numberOfCharacters; i++) {

            [_customImages addObject:[self createCustomImage]];

        }

    }

    return _customImages;

}

 

- (NSMutableArray *)boxs

{

    if (!_boxs) {

        _boxs = [NSMutableArray array];

    }

    return _boxs;

}

 

#pragma mark - KVO

 

- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionaryid> *)change context:(nullable void *)context

{

    if ([keyPath isEqualToString:@"frame"]) {

        if (self.securityCharacterType == SecurityCharacterTypeSecurityDot || self.securityCharacterType == SecurityCharacterTypeHorizontalLine) {

            

        } else if (self.securityCharacterType == SecurityCharacterTypePlainText) {

            [self.placeholderDic[@(self.securityCharacterType)] enumerateObjectsUsingBlock:^(CALayer   * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

                obj.bounds = CGRectMake(0, 0, CGRectGetWidth(self.frame)/self.numberOfCharacters, CGRectGetHeight(self.frame));

            }];

        } else {

            [self.placeholderDic[@(self.securityCharacterType)] enumerateObjectsUsingBlock:^(CALayer   * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

                if (self.securityImageSize.width == 0) {

                    obj.bounds = CGRectMake(0, 0, DEFAULT_CUSTOMIMAGE_WIDTH, DEFAULT_CUSTOMIMAGE_WIDTH);

                } else {

                    obj.bounds = CGRectMake(0, 0, self.securityImageSize.width, self.securityImageSize.height);

                }

            }];

        }

    }

}

 

#pragma mark - UITextInputTraits

 

- (UIKeyboardType)keyboardType

{

    return UIKeyboardTypeNumberPad;

}

 

#pragma mark - UIKeyInput

 

- (BOOL)hasText

{

    return self.text.length > 0;

}

 

- (void)insertText:(NSString *)text

{

    if (self.text.length < self.numberOfCharacters) {

        NSInteger index = self.text.length;

        NSMutableArray*placeholders = self.placeholderDic[@(self.securityCharacterType)];

        placeholders[index].opacity = 1;

        

        if (self.securityCharacterType == SecurityCharacterTypePlainText) {

            CATextLayer *layer = (CATextLayer *)placeholders[index];

            layer.string = text;

        }

        

        self.text = [self.text stringByAppendingString:text];

        if (index == self.numberOfCharacters - 1) {

            completion_count++;

            if (@protocol(LYPaymentFieldDelegate) && [self.delegate respondsToSelector:@selector(lYPaymentFieldDidFinishedEditing:)]) {

                [self.delegate lYPaymentFieldDidFinishedEditing:self];

            }

            !self.completion?:self.completion(self, self.text);

        } else {

            if (@protocol(LYPaymentFieldDelegate) && [self.delegate respondsToSelector:@selector(lYPaymentFieldDidBeginEditing:)]) {

                [self.delegate lYPaymentFieldDidBeginEditing:self];

            }

        }

        

        [self setNeedsLayout];

    }

}

 

- (void)deleteBackward

{

    if (self.text.length > 0) {

        self.text = [self.text substringWithRange:NSMakeRange(0, self.text.length - 1)];

        NSInteger index = self.text.length;

        NSMutableArray*placeholders = self.placeholderDic[@(self.securityCharacterType)];

        placeholders[index].opacity = 0;

        

        if (@protocol(LYPaymentFieldDelegate) && [self.delegate respondsToSelector:@selector(lYPaymentFieldDidDelete:)]) {

            [self.delegate lYPaymentFieldDidDelete:self];

        }

        

        if (!self.text.length) {

            if (@protocol(LYPaymentFieldDelegate) && [self.delegate respondsToSelector:@selector(lYPaymentFieldDidClear:)]) {

                [self.delegate lYPaymentFieldDidClear:self];

            }

        } else {

            if (@protocol(LYPaymentFieldDelegate) && [self.delegate respondsToSelector:@selector(lYPaymentFieldDidBeginEditing:)]) {

                [self.delegate lYPaymentFieldDidBeginEditing:self];

            }

        }

    }

}

 

#pragma mark - firstReponder

 

- (BOOL)canBecomeFirstResponder

{

    return YES;

}

 

- (void)hangdleAction:(id)sender

{

    [self becomeFirstResponder];

}

 

#pragma mark - public methods

 

- (void)clear

{

    self.text = @"";

    [self.placeholderDic[@(self.securityCharacterType)] setValue:@0 forKeyPath:@"opacity"];

 

    if (@protocol(LYPaymentFieldDelegate) && [self.delegate respondsToSelector:@selector(lYPaymentFieldDidClear:)]) {

        [self.delegate lYPaymentFieldDidClear:self];

    }

}

 

@end

 

NS_ASSUME_NONNULL_END

你可能感兴趣的:(装载资源)