YOUPAIHWTFCursorView.m 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. //
  2. // YOUPAIHWTFCursorView.m
  3. // CodeTextDemo
  4. //
  5. // Created by 侯万 on 2018/12/13.
  6. // Copyright © 2018 小侯爷. All rights reserved.
  7. //
  8. #import "YOUPAIHWTFCursorView.h"
  9. @interface YOUPAIHWTFCursorView ()
  10. @property (nonatomic, assign) NSInteger itemCount;
  11. @property (nonatomic, assign) CGFloat itemMargin;
  12. @property (nonatomic, assign) BOOL haveBorder;
  13. @property (nonatomic, weak) UIControl *maskView;
  14. @property (nonatomic, strong) NSMutableArray<HWCursorLabel *> *labels;
  15. @property (nonatomic, strong) NSMutableArray<UIView *> *lines;
  16. @property (nonatomic, weak) HWCursorLabel *currentLabel;
  17. @end
  18. @implementation YOUPAIHWTFCursorView
  19. #pragma mark - 初始化
  20. - (instancetype)initWithCount:(NSInteger)count margin:(CGFloat)margin haveBorder:(BOOL)isHave
  21. {
  22. if (self = [super init]) {
  23. self.itemCount = count;
  24. self.itemMargin = margin;
  25. self.haveBorder = isHave;
  26. [self configTextField];
  27. }
  28. return self;
  29. }
  30. - (void)configTextField
  31. {
  32. self.backgroundColor = [UIColor blackColor];
  33. self.labels = @[].mutableCopy;
  34. self.lines = @[].mutableCopy;
  35. UITextField *textField = [[UITextField alloc] init];
  36. //左边有个小的textfiled 不显示
  37. [textField setTextColor:[UIColor clearColor]];
  38. //隐藏光标
  39. textField.tintColor = [UIColor clearColor];
  40. textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
  41. textField.keyboardType = UIKeyboardTypeNumberPad;
  42. [textField addTarget:self action:@selector(tfEditingChanged:) forControlEvents:(UIControlEventEditingChanged)];
  43. // 小技巧:这个属性为YES,可以强制使用系统的数字键盘,缺点是重新输入时,会清空之前的内容
  44. // clearsOnBeginEditing 属性并不适用于 secureTextEntry = YES 时
  45. // textField.secureTextEntry = YES;
  46. [self addSubview:textField];
  47. self.textField = textField;
  48. // 小技巧:通过textField上层覆盖一个maskView,可以去掉textField的长按事件
  49. UIButton *maskView = [UIButton new];
  50. maskView.backgroundColor = [UIColor clearColor];
  51. [maskView addTarget:self action:@selector(clickMaskView) forControlEvents:(UIControlEventTouchUpInside)];
  52. [self addSubview:maskView];
  53. self.maskView = maskView;
  54. for (NSInteger i = 0; i < self.itemCount; i++)
  55. {
  56. HWCursorLabel *label = [HWCursorLabel new];
  57. if (self.haveBorder) {
  58. label.textAlignment = NSTextAlignmentCenter;
  59. label.textColor = LZ273145Color;
  60. label.layer.cornerRadius = 56/2;
  61. label.layer.masksToBounds = YES;
  62. label.backgroundColor = LZF5F4F7Color;
  63. label.font = [UIFont fontWithName:@"PingFangSC-Regular" size:18];
  64. }else{
  65. label.textAlignment = NSTextAlignmentCenter;
  66. //密码颜色
  67. label.textColor = [UIColor whiteColor];
  68. label.font = [UIFont fontWithName:@"PingFangSC-Regular" size:41.5];
  69. }
  70. [self addSubview:label];
  71. [self.labels addObject:label];
  72. }
  73. for (NSInteger i = 0; i < self.itemCount; i++)
  74. {
  75. UIView *line = [UIView new];
  76. //下划线颜色
  77. if (self.haveBorder) {
  78. line.backgroundColor = [UIColor clearColor];
  79. }else{
  80. line.backgroundColor = [UIColor whiteColor];
  81. }
  82. [self addSubview:line];
  83. [self.lines addObject:line];
  84. }
  85. }
  86. - (void)layoutSubviews
  87. {
  88. [super layoutSubviews];
  89. if (self.labels.count != self.itemCount) return;
  90. CGFloat temp = self.bounds.size.width - (self.itemMargin * (self.itemCount - 1));
  91. CGFloat w = temp / self.itemCount;
  92. CGFloat x = 0;
  93. for (NSInteger i = 0; i < self.labels.count; i++)
  94. {
  95. x = i * (w + self.itemMargin);
  96. UILabel *label = self.labels[i];
  97. label.frame = CGRectMake(x, 0, w, self.bounds.size.height);
  98. UIView *line = self.lines[i];
  99. line.frame = CGRectMake(x, self.bounds.size.height - 1, w, 1);
  100. }
  101. self.textField.frame = self.bounds;
  102. self.maskView.frame = self.bounds;
  103. }
  104. #pragma mark - 编辑改变
  105. - (void)tfEditingChanged:(UITextField *)textField
  106. {
  107. if (textField.text.length > self.itemCount) {
  108. textField.text = [textField.text substringWithRange:NSMakeRange(0, self.itemCount)];
  109. }
  110. for (int i = 0; i < self.itemCount; i++)
  111. {
  112. UILabel *label = [self.labels objectAtIndex:i];
  113. if (i < textField.text.length) {
  114. if(textField.isSecureTextEntry)
  115. {
  116. label.text = @"*";
  117. }
  118. else
  119. {
  120. label.text = [textField.text substringWithRange:NSMakeRange(i, 1)];
  121. }
  122. } else {
  123. label.text = nil;
  124. }
  125. }
  126. [self cursor];
  127. // 输入完毕后,自动隐藏键盘
  128. if (textField.text.length >= self.itemCount) {
  129. [self.currentLabel stopAnimating];
  130. [textField resignFirstResponder];
  131. if([_delegate respondsToSelector:@selector(youpaifinputFinished:)])
  132. {
  133. [_delegate youpaifinputFinished:textField.text];
  134. }
  135. }
  136. }
  137. - (void)clickMaskView
  138. {
  139. [self.textField becomeFirstResponder];
  140. [self cursor];
  141. }
  142. - (BOOL)endEditing:(BOOL)force
  143. {
  144. dispatch_async(dispatch_get_main_queue(), ^{
  145. [self.textField endEditing:force];
  146. [self.currentLabel stopAnimating];
  147. });
  148. return [super endEditing:force];
  149. }
  150. #pragma mark - 处理光标
  151. - (void)cursor
  152. {
  153. [self.currentLabel stopAnimating];
  154. NSInteger index = self.code.length;
  155. if (index < 0) index = 0;
  156. if (index >= self.labels.count) index = self.labels.count - 1;
  157. HWCursorLabel *label = [self.labels objectAtIndex:index];
  158. [label startAnimating];
  159. self.currentLabel = label;
  160. }
  161. - (NSString *)code
  162. {
  163. return self.textField.text;
  164. }
  165. @end
  166. // ------------------------------------------------------------------------
  167. // -----------------------------HWCursorLabel------------------------------
  168. // ------------------------------------------------------------------------
  169. @implementation HWCursorLabel
  170. - (instancetype)initWithFrame:(CGRect)frame
  171. {
  172. self = [super initWithFrame:frame];
  173. if (self) {
  174. [self youpaifsetupView];
  175. }
  176. return self;
  177. }
  178. - (instancetype)initWithCoder:(NSCoder *)coder
  179. {
  180. self = [super initWithCoder:coder];
  181. if (self) {
  182. [self youpaifsetupView];
  183. }
  184. return self;
  185. }
  186. #pragma mark - 初始化View
  187. - (void)youpaifsetupView
  188. {
  189. UIView *cursorView = [[UIView alloc] init];
  190. cursorView.backgroundColor = LZ7C69FEColor;
  191. cursorView.alpha = 0;
  192. [self addSubview:cursorView];
  193. _cursorView = cursorView;
  194. }
  195. - (void)layoutSubviews
  196. {
  197. [super layoutSubviews];
  198. CGFloat h = 30;
  199. CGFloat w = 2;
  200. CGFloat x = self.bounds.size.width * 0.5;
  201. CGFloat y = self.bounds.size.height * 0.5;
  202. self.cursorView.frame = CGRectMake(0, 0, w, h);
  203. self.cursorView.center = CGPointMake(x, y);
  204. }
  205. - (void)startAnimating
  206. {
  207. if (self.text.length > 0) return;
  208. CABasicAnimation *oa = [CABasicAnimation animationWithKeyPath:@"opacity"];
  209. oa.fromValue = [NSNumber numberWithFloat:0];
  210. oa.toValue = [NSNumber numberWithFloat:1];
  211. oa.duration = 1;
  212. oa.repeatCount = MAXFLOAT;
  213. oa.removedOnCompletion = NO;
  214. oa.fillMode = kCAFillModeForwards;
  215. oa.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
  216. [self.cursorView.layer addAnimation:oa forKey:@"opacity"];
  217. }
  218. - (void)stopAnimating
  219. {
  220. [self.cursorView.layer removeAnimationForKey:@"opacity"];
  221. }
  222. @end