MOInputCodeView.m 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. //
  2. // MOInputCodeView.m
  3. // MiMoLive
  4. //
  5. // Created by MiMo on 2025/6/3.
  6. //
  7. #import "MOInputCodeView.h"
  8. @interface MOInputCodeView ()<UITextFieldDelegate>
  9. @property (nonatomic, strong) UITextField *hiddenField;
  10. @property (nonatomic, strong) NSMutableArray<UILabel *> *digitLabels;
  11. @property (nonatomic, strong) UIView *cursorView;
  12. @end
  13. @implementation MOInputCodeView
  14. - (instancetype)initWithFrame:(CGRect)frame {
  15. self = [super initWithFrame:frame];
  16. if (self) {
  17. [self setupUI];
  18. }
  19. return self;
  20. }
  21. - (void)setupUI {
  22. self.digitLabels = [NSMutableArray array];
  23. UIImage *slotBg = [UIImage imageNamed:@"img_login_code_bg"];
  24. CGFloat boxSize = kScaleWidth(64);
  25. CGFloat spacing = kScaleWidth(24);
  26. NSInteger count = 4;
  27. for (int i = 0; i < count; i++) {
  28. UIImageView *box = [[UIImageView alloc] initWithImage:slotBg];
  29. box.contentMode = UIViewContentModeScaleToFill;
  30. box.userInteractionEnabled = NO;
  31. [self addSubview:box];
  32. [box mas_makeConstraints:^(MASConstraintMaker *make) {
  33. make.size.mas_equalTo(CGSizeMake(boxSize, boxSize));
  34. make.left.mas_equalTo(i * (boxSize + spacing));
  35. make.top.bottom.equalTo(self);
  36. }];
  37. UILabel *label = [[UILabel alloc] init];
  38. label.font = [MOTextTools poppinsMediumFont:32];
  39. label.textAlignment = NSTextAlignmentCenter;
  40. label.textColor = kBaseTextColor_1;
  41. [box addSubview:label];
  42. [label mas_makeConstraints:^(MASConstraintMaker *make) {
  43. make.edges.equalTo(box);
  44. }];
  45. [self.digitLabels addObject:label];
  46. }
  47. self.hiddenField = [[UITextField alloc] init];
  48. self.hiddenField.keyboardType = UIKeyboardTypeNumberPad;
  49. self.hiddenField.textColor = UIColor.clearColor;
  50. self.hiddenField.tintColor = UIColor.clearColor;
  51. self.hiddenField.delegate = self;
  52. [self.hiddenField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
  53. [self addSubview:self.hiddenField];
  54. [self.hiddenField mas_makeConstraints:^(MASConstraintMaker *make) {
  55. make.edges.equalTo(self);
  56. }];
  57. self.cursorView = [[UIView alloc] init];
  58. self.cursorView.backgroundColor = [MOTools colorWithHexString:@"#4363FF"];
  59. self.cursorView.hidden = YES;
  60. self.cursorView.layer.cornerRadius = 1;
  61. self.cursorView.layer.masksToBounds = YES;
  62. [self addSubview:self.cursorView];
  63. [self.cursorView mas_makeConstraints:^(MASConstraintMaker *make) {
  64. make.width.mas_equalTo(2);
  65. make.height.mas_equalTo(24);
  66. make.center.equalTo(self); // 初始占位,稍后更新位置
  67. }];
  68. // 添加光标闪烁动画
  69. CABasicAnimation *blink = [CABasicAnimation animationWithKeyPath:@"opacity"];
  70. blink.fromValue = @1.0;
  71. blink.toValue = @0.0;
  72. blink.duration = 0.8;
  73. blink.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
  74. blink.autoreverses = YES;
  75. blink.repeatCount = HUGE_VALF;
  76. [self.cursorView.layer addAnimation:blink forKey:@"blink"];
  77. }
  78. - (void)showKeyboard {
  79. [self.hiddenField becomeFirstResponder];
  80. [self moveCursorToIndex:0];
  81. }
  82. - (void)textFieldDidChange:(UITextField *)textField {
  83. NSString *text = textField.text;
  84. if (text.length > 4) {
  85. text = [text substringToIndex:4];
  86. textField.text = text;
  87. }
  88. for (int i = 0; i < 4; i++) {
  89. UILabel *label = self.digitLabels[i];
  90. if (i < text.length) {
  91. label.text = [text substringWithRange:NSMakeRange(i, 1)];
  92. } else {
  93. label.text = @"";
  94. }
  95. }
  96. if (text.length == 4 && self.inputCompleted) {
  97. self.inputCompleted(text);
  98. }
  99. NSInteger index = text.length; // 下一个待输入框索引
  100. if (index >= 0 && index < self.digitLabels.count) {
  101. UILabel *targetLabel = self.digitLabels[index];
  102. [self.cursorView mas_remakeConstraints:^(MASConstraintMaker *make) {
  103. make.width.mas_equalTo(2);
  104. make.height.mas_equalTo(24);
  105. make.center.equalTo(targetLabel);
  106. }];
  107. self.cursorView.hidden = NO;
  108. } else {
  109. self.cursorView.hidden = YES;
  110. }
  111. }
  112. - (void)clear {
  113. self.hiddenField.text = @"";
  114. for (UILabel *label in self.digitLabels) {
  115. label.text = @"";
  116. }
  117. self.cursorView.hidden = NO;
  118. [self moveCursorToIndex:0];
  119. }
  120. - (void)moveCursorToIndex:(NSInteger)index {
  121. if (index >= 0 && index < self.digitLabels.count) {
  122. UILabel *targetLabel = self.digitLabels[index];
  123. [self.cursorView mas_remakeConstraints:^(MASConstraintMaker *make) {
  124. make.width.mas_equalTo(2);
  125. make.height.mas_equalTo(24);
  126. make.center.equalTo(targetLabel);
  127. }];
  128. self.cursorView.hidden = NO;
  129. } else {
  130. self.cursorView.hidden = YES;
  131. }
  132. }
  133. @end