Files
CRBoxInputView/PodCode/Classes/CRBoxInputView.m

557 lines
15 KiB
Mathematica
Raw Normal View History

2019-01-03 18:03:44 +08:00
//
// CRBoxInputView.m
// CRBoxInputView
//
// Created by Chobits on 2019/1/3.
// Copyright © 2019 Chobits. All rights reserved.
//
#import "CRBoxInputView.h"
#import <Masonry/Masonry.h>
2019-01-03 18:43:31 +08:00
#import "CRBoxTextView.h"
2019-01-03 18:03:44 +08:00
2019-01-03 19:13:36 +08:00
typedef NS_ENUM(NSInteger, CRBoxTextChangeType) {
CRBoxTextChangeType_NoChange,
CRBoxTextChangeType_Insert,
CRBoxTextChangeType_Delete,
};
@interface CRBoxInputView () <UICollectionViewDataSource, UICollectionViewDelegate, UITextFieldDelegate>
2019-01-03 18:03:44 +08:00
{
2019-01-03 19:13:36 +08:00
NSInteger _oldLength;
BOOL _ifNeedBeginEdit;
2019-01-03 18:03:44 +08:00
}
2019-11-10 16:45:45 +08:00
@property (nonatomic, strong) UITapGestureRecognizer *tapGR;
2019-01-03 18:43:31 +08:00
@property (nonatomic, strong) CRBoxTextView *textView;
2019-01-03 18:03:44 +08:00
@property (nonatomic, strong) UICollectionView *mainCollectionView;
2019-01-03 19:13:36 +08:00
@property (nonatomic, strong) NSMutableArray <NSString *> *valueArr;
2019-01-04 15:28:43 +08:00
@property (nonatomic, strong) NSMutableArray <CRBoxInputCellProperty *> *cellPropertyArr;
2019-01-03 18:03:44 +08:00
@end
@implementation CRBoxInputView
2019-01-04 15:46:16 +08:00
- (instancetype)initWithFrame:(CGRect)frame{
2019-01-03 18:03:44 +08:00
self = [super initWithFrame:frame];
if (self) {
[self initDefaultValue];
[self addNotificationObserver];
2019-01-03 18:03:44 +08:00
}
return self;
}
2019-01-04 15:46:16 +08:00
- (instancetype)init
2019-01-03 18:03:44 +08:00
{
self = [super init];
if (self) {
[self initDefaultValue];
[self addNotificationObserver];
2019-01-03 18:03:44 +08:00
}
return self;
}
2020-01-13 18:47:39 +08:00
- (void)dealloc
{
[self removeNotificationObserver];
}
#pragma mark - Notification Observer
- (void)addNotificationObserver
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
}
2020-01-13 18:47:39 +08:00
- (void)removeNotificationObserver {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)applicationWillResignActive:(NSNotification *)notification
{
// home
}
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
//
[_mainCollectionView reloadData];
}
2019-01-06 19:40:28 +08:00
#pragma mark - You can inherit
- (void)initDefaultValue
{
2019-01-03 19:13:36 +08:00
_oldLength = 0;
2019-01-03 19:54:13 +08:00
self.ifNeedSecurity = NO;
2019-01-03 19:44:13 +08:00
self.securityDelay = 0.3;
2019-01-03 18:03:44 +08:00
self.codeLength = 4;
self.ifNeedCursor = YES;
2019-01-07 12:23:58 +08:00
self.keyBoardType = UIKeyboardTypeNumberPad;
2019-01-03 18:03:44 +08:00
self.backgroundColor = [UIColor clearColor];
_valueArr = [NSMutableArray new];
_ifNeedBeginEdit = NO;
2019-01-03 18:03:44 +08:00
}
#pragma mark - LoadAndPrepareView
2019-01-04 15:46:16 +08:00
- (void)loadAndPrepareView
{
[self loadAndPrepareViewWithBeginEdit:YES];
}
- (void)loadAndPrepareViewWithBeginEdit:(BOOL)beginEdit
2019-01-04 15:46:16 +08:00
{
2019-01-03 18:03:44 +08:00
if (_codeLength<=0) {
NSAssert(NO, @"请输入大于0的验证码位数");
return;
}
2019-01-04 15:46:16 +08:00
[self generateCellPropertyArr];
2019-01-04 15:28:43 +08:00
2019-01-04 15:46:16 +08:00
// mainCollectionView
2019-01-03 18:03:44 +08:00
[self addSubview:self.mainCollectionView];
[self.mainCollectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(UIEdgeInsetsZero);
}];
2019-01-04 15:46:16 +08:00
// textView
2019-01-03 18:03:44 +08:00
[self addSubview:self.textView];
[self.textView mas_makeConstraints:^(MASConstraintMaker *make) {
2019-11-10 16:41:12 +08:00
// make.edges.mas_equalTo(UIEdgeInsetsZero);
make.width.height.mas_equalTo(0);
make.left.top.mas_equalTo(0);
2019-01-03 18:03:44 +08:00
}];
2019-11-10 16:45:45 +08:00
// tap
if (self.tapGR.view != self) {
[self addGestureRecognizer:self.tapGR];
}
if (![self.textView.text isEqualToString:self.customCellProperty.originValue]) {
self.textView.text = self.customCellProperty.originValue;
[self textDidChange:self.textView];
}
2019-11-10 16:45:45 +08:00
if (beginEdit) {
[self beginEdit];
}
2019-01-03 18:03:44 +08:00
}
2019-01-04 15:46:16 +08:00
- (void)generateCellPropertyArr
2019-01-04 15:28:43 +08:00
{
[self.cellPropertyArr removeAllObjects];
for (int i = 0; i < self.codeLength; i++) {
[self.cellPropertyArr addObject:[self.customCellProperty copy]];
}
}
#pragma mark - Reload Input View
- (void)reloadInputString:(NSString *_Nullable)value
{
if (![self.textView.text isEqualToString:value]) {
self.textView.text = value;
2020-01-20 15:31:03 +08:00
[self baseTextDidChange:self.textView manualInvoke:YES];
}
}
#pragma mark - UITextFieldDelegate
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
_ifNeedBeginEdit = YES;
2020-01-20 16:20:36 +08:00
if (self.textEditStatusChangeblock) {
self.textEditStatusChangeblock(CRTextEditStatus_BeginEdit);
}
[self.mainCollectionView reloadData];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
_ifNeedBeginEdit = NO;
2020-01-20 16:20:36 +08:00
if (self.textEditStatusChangeblock) {
self.textEditStatusChangeblock(CRTextEditStatus_EndEdit);
}
[self.mainCollectionView reloadData];
}
2019-01-03 18:03:44 +08:00
#pragma mark - TextViewEdit
2019-01-04 15:46:16 +08:00
- (void)beginEdit{
2020-01-20 16:20:36 +08:00
if (![self.textView isFirstResponder]) {
[self.textView becomeFirstResponder];
}
2019-01-03 18:03:44 +08:00
}
2019-01-04 15:46:16 +08:00
- (void)endEdit{
2020-01-20 16:20:36 +08:00
if ([self.textView isFirstResponder]) {
[self.textView resignFirstResponder];
}
2019-01-03 18:03:44 +08:00
}
- (void)clearAll
{
[self clearAllWithBeginEdit:YES];
}
- (void)clearAllWithBeginEdit:(BOOL)beginEdit
{
2019-01-03 19:16:09 +08:00
_oldLength = 0;
[_valueArr removeAllObjects];
2019-01-03 18:03:44 +08:00
self.textView.text = @"";
[self allSecurityClose];
2019-01-03 19:16:09 +08:00
[self.mainCollectionView reloadData];
[self triggerBlock];
if (beginEdit) {
[self beginEdit];
}
2019-01-03 18:03:44 +08:00
}
#pragma mark - UITextFieldDidChange
2020-01-20 15:31:03 +08:00
- (void)textDidChange:(UITextField *)textField {
[self baseTextDidChange:textField manualInvoke:NO];
}
/**
* textDidChange
* manualInvoke
*/
- (void)baseTextDidChange:(UITextField *)textField manualInvoke:(BOOL)manualInvoke {
2019-01-03 18:03:44 +08:00
__weak typeof(self) weakSelf = self;
NSString *verStr = textField.text;
2019-01-03 18:03:44 +08:00
//
verStr = [verStr stringByReplacingOccurrencesOfString:@" " withString:@""];
if (verStr.length >= _codeLength) {
verStr = [verStr substringToIndex:_codeLength];
[self endEdit];
}
textField.text = verStr;
2019-01-03 18:03:44 +08:00
2019-01-03 19:13:36 +08:00
// /
CRBoxTextChangeType boxTextChangeType = CRBoxTextChangeType_NoChange;
if (verStr.length > _oldLength) {
boxTextChangeType = CRBoxTextChangeType_Insert;
}else if (verStr.length < _oldLength){
boxTextChangeType = CRBoxTextChangeType_Delete;
}
2019-01-03 18:03:44 +08:00
// _valueArr
2019-01-03 19:13:36 +08:00
if (boxTextChangeType == CRBoxTextChangeType_Delete) {
2019-01-04 16:09:03 +08:00
[self setSecurityShow:NO index:_valueArr.count-1];
2019-01-03 19:13:36 +08:00
[_valueArr removeLastObject];
2019-01-04 16:05:34 +08:00
2019-01-03 19:13:36 +08:00
}else if (boxTextChangeType == CRBoxTextChangeType_Insert){
if (verStr.length > 0) {
2019-01-03 19:39:22 +08:00
if (_valueArr.count > 0) {
[self replaceValueArrToAsteriskWithIndex:_valueArr.count - 1 needEqualToCount:NO];
}
// NSString *subStr = [verStr substringWithRange:NSMakeRange(verStr.length - 1, 1)];
2019-11-10 17:03:15 +08:00
// [strongSelf.valueArr addObject:subStr];
[_valueArr removeAllObjects];
[verStr enumerateSubstringsInRange:NSMakeRange(0, verStr.length) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
2019-11-10 17:03:15 +08:00
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf.valueArr addObject:substring];
}];
2020-01-20 15:31:03 +08:00
if (self.ifNeedSecurity) {
if (manualInvoke) {
//
[self delaySecurityProcessAll];
}else {
//
[self delaySecurityProcessLastOne];
}
}
2019-01-03 19:13:36 +08:00
}
}
2019-01-03 18:03:44 +08:00
[_mainCollectionView reloadData];
2019-01-03 19:16:09 +08:00
_oldLength = verStr.length;
if (boxTextChangeType != CRBoxTextChangeType_NoChange) {
[self triggerBlock];
}
2019-01-03 19:16:09 +08:00
}
2019-01-04 16:05:34 +08:00
#pragma mark - Control security show
2019-01-04 16:09:03 +08:00
- (void)setSecurityShow:(BOOL)isShow index:(NSInteger)index
2019-01-04 16:05:34 +08:00
{
if (index < 0) {
2020-01-20 15:31:03 +08:00
NSAssert(NO, @"index必须大于等于0");
2019-01-04 16:05:34 +08:00
return;
}
CRBoxInputCellProperty *cellProperty = self.cellPropertyArr[index];
2019-01-04 16:09:03 +08:00
cellProperty.ifShowSecurity = isShow;
2019-01-04 16:05:34 +08:00
}
- (void)allSecurityClose
2019-01-04 16:05:34 +08:00
{
[self.cellPropertyArr enumerateObjectsUsingBlock:^(CRBoxInputCellProperty * _Nonnull cellProperty, NSUInteger idx, BOOL * _Nonnull stop) {
if (cellProperty.ifShowSecurity == YES) {
cellProperty.ifShowSecurity = NO;
}
}];
}
- (void)allSecurityOpen
{
[self.cellPropertyArr enumerateObjectsUsingBlock:^(CRBoxInputCellProperty * _Nonnull cellProperty, NSUInteger idx, BOOL * _Nonnull stop) {
if (cellProperty.ifShowSecurity == NO) {
cellProperty.ifShowSecurity = YES;
}
}];
}
2019-01-04 16:05:34 +08:00
#pragma mark - Trigger block
2019-01-03 19:16:09 +08:00
- (void)triggerBlock
{
2019-01-03 18:03:44 +08:00
if (self.textDidChangeblock) {
BOOL isFinished = _valueArr.count == _codeLength ? YES : NO;
2019-01-03 19:16:09 +08:00
self.textDidChangeblock(_textView.text, isFinished);
2019-01-03 18:03:44 +08:00
}
2019-01-03 19:13:36 +08:00
}
2020-01-20 15:39:36 +08:00
#pragma mark - Asterisk
2020-01-20 15:31:03 +08:00
/**
*
* needEqualToCount
*/
2019-01-03 19:39:22 +08:00
- (void)replaceValueArrToAsteriskWithIndex:(NSInteger)index needEqualToCount:(BOOL)needEqualToCount
2019-01-03 19:13:36 +08:00
{
2019-01-03 19:54:13 +08:00
if (!self.ifNeedSecurity) {
return;
}
2019-01-03 19:39:22 +08:00
if (needEqualToCount && index != _valueArr.count - 1) {
return;
}
2019-01-04 16:09:03 +08:00
[self setSecurityShow:YES index:index];
2019-01-03 19:39:22 +08:00
}
2020-01-20 15:39:36 +08:00
#pragma mark
2020-01-20 15:31:03 +08:00
- (void)delaySecurityProcessLastOne
2019-01-03 19:39:22 +08:00
{
2019-11-10 17:03:15 +08:00
__weak __typeof(self)weakSelf = self;
2020-01-20 15:31:03 +08:00
[self delayAfter:self.securityDelay dealBlock:^{
2019-11-10 17:03:15 +08:00
__strong __typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf.valueArr.count > 0) {
[strongSelf replaceValueArrToAsteriskWithIndex:strongSelf.valueArr.count-1 needEqualToCount:YES];
2019-01-03 19:39:22 +08:00
dispatch_async(dispatch_get_main_queue(), ^{
2019-11-10 17:03:15 +08:00
[strongSelf.mainCollectionView reloadData];
2019-01-03 19:39:22 +08:00
});
2019-01-03 19:13:36 +08:00
}
}];
}
2020-01-20 15:39:36 +08:00
#pragma mark
2020-01-20 15:31:03 +08:00
- (void)delaySecurityProcessAll
{
__weak __typeof(self)weakSelf = self;
[self.valueArr enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf replaceValueArrToAsteriskWithIndex:idx needEqualToCount:NO];
}];
[self.mainCollectionView reloadData];
}
2019-01-03 19:13:36 +08:00
#pragma mark - DelayBlock
- (void)delayAfter:(CGFloat)delayTime dealBlock:(void (^)(void))dealBlock
{
dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayTime *NSEC_PER_SEC));
dispatch_after(timer, dispatch_get_main_queue(), ^{
if (dealBlock) {
dealBlock();
}
});
2019-01-03 18:03:44 +08:00
}
#pragma mark - UICollectionViewDataSource
2019-01-04 15:46:16 +08:00
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
2019-01-03 18:03:44 +08:00
{
return _codeLength;
}
2019-01-04 15:46:16 +08:00
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
2019-01-03 18:03:44 +08:00
{
2019-01-06 19:40:28 +08:00
id tempCell = [self customCollectionView:collectionView cellForItemAtIndexPath:indexPath];
2019-01-04 20:07:30 +08:00
2019-01-06 19:40:28 +08:00
if ([tempCell isKindOfClass:[CRBoxInputCell class]]) {
CRBoxInputCell *cell = (CRBoxInputCell *)tempCell;
cell.ifNeedCursor = self.ifNeedCursor;
// CellProperty
CRBoxInputCellProperty *cellProperty = self.cellPropertyArr[indexPath.row];
cellProperty.index = indexPath.row;
2019-07-16 14:27:20 +08:00
NSString *currentPlaceholderStr = nil;
if (_placeholderText.length > indexPath.row) {
currentPlaceholderStr = [_placeholderText substringWithRange:NSMakeRange(indexPath.row, 1)];
2019-07-16 14:59:37 +08:00
cellProperty.cellPlaceholderText = currentPlaceholderStr;
2019-07-16 14:27:20 +08:00
}
2019-01-06 19:40:28 +08:00
// setOriginValue
NSUInteger focusIndex = _valueArr.count;
if (_valueArr.count > 0 && indexPath.row <= focusIndex - 1) {
2020-01-20 15:51:05 +08:00
[cellProperty setMyOriginValue:_valueArr[indexPath.row]];
2019-07-16 14:41:42 +08:00
}else{
2020-01-20 15:51:05 +08:00
[cellProperty setMyOriginValue:@""];
2019-01-06 19:40:28 +08:00
}
cell.boxInputCellProperty = cellProperty;
if (_ifNeedBeginEdit) {
cell.selected = indexPath.row == focusIndex ? YES : NO;
}else{
cell.selected = NO;
}
2019-01-03 18:03:44 +08:00
}
2019-01-06 19:40:28 +08:00
return tempCell;
2019-01-03 18:03:44 +08:00
}
2019-01-04 16:05:34 +08:00
#pragma mark - Qiuck set
- (void)quickSetSecuritySymbol:(NSString *)securitySymbol
{
if (securitySymbol.length != 1) {
securitySymbol = @"✱";
}
self.customCellProperty.securitySymbol = securitySymbol;
}
2019-01-06 18:59:10 +08:00
#pragma mark - You can rewrite
2019-01-06 19:40:28 +08:00
- (UICollectionViewCell *)customCollectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
2019-01-06 18:59:10 +08:00
{
CRBoxInputCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CRBoxInputCellID forIndexPath:indexPath];
return cell;
}
2019-01-03 18:03:44 +08:00
#pragma mark - Setter & Getter
2019-11-10 16:45:45 +08:00
- (UITapGestureRecognizer *)tapGR
{
if (!_tapGR) {
_tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(beginEdit)];
}
return _tapGR;
}
2019-01-04 15:46:16 +08:00
- (UICollectionView *)mainCollectionView
2019-01-03 18:03:44 +08:00
{
if (!_mainCollectionView) {
_mainCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:self.boxFlowLayout];
_mainCollectionView.showsHorizontalScrollIndicator = NO;
_mainCollectionView.backgroundColor = [UIColor clearColor];
_mainCollectionView.delegate = self;
_mainCollectionView.dataSource = self;
2019-01-07 14:30:55 +08:00
_mainCollectionView.layer.masksToBounds = NO;
_mainCollectionView.clipsToBounds = NO;
2019-01-03 18:03:44 +08:00
[_mainCollectionView registerClass:[CRBoxInputCell class] forCellWithReuseIdentifier:CRBoxInputCellID];
}
return _mainCollectionView;
}
2019-01-04 15:46:16 +08:00
- (CRBoxFlowLayout *)boxFlowLayout
2019-01-03 18:03:44 +08:00
{
if (!_boxFlowLayout) {
_boxFlowLayout = [CRBoxFlowLayout new];
2019-01-07 12:46:24 +08:00
_boxFlowLayout.itemSize = CGSizeMake(42, 47);
2019-01-03 18:03:44 +08:00
}
return _boxFlowLayout;
}
- (void)setCodeLength:(NSInteger)codeLength
{
_codeLength = codeLength;
self.boxFlowLayout.itemNum = codeLength;
}
2019-01-04 15:46:16 +08:00
- (void)setKeyBoardType:(UIKeyboardType)keyBoardType{
2019-01-03 18:03:44 +08:00
_keyBoardType = keyBoardType;
self.textView.keyboardType = keyBoardType;
}
2019-01-04 15:46:16 +08:00
- (CRBoxTextView *)textView{
2019-01-03 18:03:44 +08:00
if (!_textView) {
2019-01-03 18:43:31 +08:00
_textView = [CRBoxTextView new];
2019-11-10 16:41:12 +08:00
// _textView.alpha = 0.1;
// _textView.tintColor = [UIColor clearColor];
// _textView.backgroundColor = [UIColor clearColor];
// _textView.textColor = [UIColor clearColor];
_textView.delegate = self;
[_textView addTarget:self action:@selector(textDidChange:) forControlEvents:UIControlEventEditingChanged];
2019-01-03 18:03:44 +08:00
}
return _textView;
}
- (void)setTextContentType:(UITextContentType)textContentType
{
_textContentType = textContentType;
_textView.textContentType = textContentType;
}
2019-01-04 15:28:43 +08:00
- (CRBoxInputCellProperty *)customCellProperty
{
if (!_customCellProperty) {
_customCellProperty = [CRBoxInputCellProperty new];
}
return _customCellProperty;
}
- (NSMutableArray <CRBoxInputCellProperty *> *)cellPropertyArr
{
if (!_cellPropertyArr) {
_cellPropertyArr = [NSMutableArray new];
}
return _cellPropertyArr;
2019-01-03 19:50:45 +08:00
}
2019-01-07 15:20:30 +08:00
- (NSString *)textValue
{
return _textView.text;
}
2019-07-01 11:42:27 +08:00
@synthesize inputAccessoryView = _inputAccessoryView;
2019-07-01 11:22:29 +08:00
- (void)setInputAccessoryView:(UIView *)inputAccessoryView
{
2019-07-01 11:42:27 +08:00
_inputAccessoryView = inputAccessoryView;
self.textView.inputAccessoryView = _inputAccessoryView;
2019-07-01 11:22:29 +08:00
}
- (UIView *)inputAccessoryView
{
2019-07-01 11:42:27 +08:00
return _inputAccessoryView;
2019-07-01 11:22:29 +08:00
}
- (void)setIfNeedSecurity:(BOOL)ifNeedSecurity
{
_ifNeedSecurity = ifNeedSecurity;
if (ifNeedSecurity == YES) {
[self allSecurityOpen];
}else{
[self allSecurityClose];
}
dispatch_async(dispatch_get_main_queue(), ^{
2019-11-10 17:03:15 +08:00
[self.mainCollectionView reloadData];
});
}
2019-01-03 18:03:44 +08:00
@end