Просмотр кода OTP | Кодементор

Два года назад я сделал для этой цели просмотр. Подробности у меня на гитхабе: https://github.com/nguyentruongky/ActiveCode.

Это 100% код, без автоматической верстки. Сегодня я делаю другое представление с той же целью, но использую автоматическую компоновку, улучшенный пользовательский интерфейс и намного проще в обслуживании.

Интерфейс будет таким.

Вы можете попробовать это сами, прежде чем следовать этому руководству. Найдите свое решение, которое может быть намного лучше, чем это.

Идея решения:

  • Добавьте количество меток для отображения вводимых букв.
  • Добавьте текстовое поле для отображения клавиатуры, но настройте его так, чтобы оно перекрывалось другим представлением (или выходило за рамки).
  • Захватите каждый введенный символ и обновите метки.

Давай сделаем это.

Начальное представление с необходимым количеством цифр и действием для проверки вашего OTP с вашего контроллера. Количество цифр должно быть меньше 6 для хорошего пользовательского интерфейса.

private var digitCount = 0
private var validate: ((String) -> Void)?
convenience init(digitCount: Int, validate: @escaping ((String) -> Void)) {
    self.init(frame: CGRect.zero)
    self.digitCount = digitCount
    self.validate = validate
    setupView()
}
  • Запустите представление с количеством цифр и обратным вызовом для проверки ввода кода.
override func setupView() {
  // (1)
  guard digitCount > 0 else { return }

  // (2)
  var constraints = "H:|-8-"
  for i in 0 ..< digitCount {
      let label = makeLabel()
      if i > 0 {
          label.width(toView: labels[0])
      }
      constraints += "[v\(i)]-8-"
  }
  constraints += "|"
  addConstraints(withFormat: constraints, arrayOf: labels)
  height(60)

  // (3)
  setCode(at: 0, active: true)
  hiddenTextField.becomeFirstResponder()
  addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(becomeFirstResponder)))
}

private func makeLabel() -> UILabel {
  let label = knUIMaker.makeLabel(font: UIFont.systemFont(ofSize: 45),
                              color: color_69_125_245,
                              alignment: .center)
  // (4)
  label.createRoundCorner(5)
  label.createBorder(0.5, color: color_102)

  // (5)
  addSubview(label)
  label.vertical(toView: self)
  labels.append(label)
  return label
}

(1)

  • Предотвратить запуск кода, пока нет цифры. Поддерживайте только просмотр инициализации по коду с init(digitCount:validate)поэтому следует предотвратить неправильное поведение другого способа инициализации.

(2)

  • Установите код автоматической разметки. Создайте строку языка визуального формата (например: "H:|-8-[v0]-[v1]-8-|"). Деталь здесь.

  • Чтобы убедиться, что все цифровые индикаторы имеют одинаковую ширину, я устанавливаю widthConstraint равным первому индикатору.

(3)

  • Мелкие мелочи, сделайте первый индикатор активным, установите фокус на hiddenTextField, чтобы отобразить клавиатуру.

(4)

  • Вот так выглядит индикатор. Хотите изменить пользовательский интерфейс, просто сделайте это здесь.

(5)

  • Это метка для отображения индикатора.

Добавьте UITextField, который перекрывается, чтобы использовать его клавиатуру и делегат. При каждом вводе ключа я буду обновлять индикатор цифр, поймав символ в UITextFieldDelegate.

lazy var hiddenTextField = addHiddenTextField()
private func addHiddenTextField() -> UITextField {
    let tf = UITextField()
    tf.translatesAutoresizingMaskIntoConstraints = false
    tf.keyboardType = .numberPad
    tf.isHidden = true
    tf.delegate = self

    addSubviews(views: tf)
    tf.fill(toView: self)

    return tf
}
override func becomeFirstResponder() -> Bool {
    hiddenTextField.becomeFirstResponder()
    return true
}

Соответствовать UITextFieldDelegate и метод обновления textfield(shouldChangeCharactersIn:replacementString). Это самое главное в этом классе.

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    var newText = string
    // (1)
    if isInvalid {
        isInvalid = false
    } else {
        newText = (textField.text! as NSString).replacingCharacters(in: range, with: string)
    }

    // (2)
    let codeLength = newText.length
    guard codeLength <= digitCount else { return false }
    textField.text = newText

    // (3)
    func setTextToActiveBox() {
        for i in 0 ..< codeLength {
            let char = textField.text!.substring(from: i, to: i)
            labels[i].text = char
            setCode(at: i, active: true)
        }
    }

    // (4)
    func setTextToInactiveBox() {
        for i in codeLength ..< digitCount {
            labels[i].text = ""
            setCode(at: i, active: false)
        }

        if codeLength <= digitCount - 1 {
            setCode(at: codeLength, active: true)
        }
    }

    setTextToActiveBox()
    setTextToInactiveBox()

    if codeLength == digitCount {
        validateCode(code: textField.text!)
    }
    return false
}

(1)

  • Сбросьте все поля, когда код недействителен, и введите новый символ.

(2)(3)(4)

  • Обновите каждого персонажа из hiddenTextField к каждому индикаторному полю. Остальные ящики будут пустыми.

Основная часть готова. Второстепенные методы, свойства находятся в lib на github. Ссылка https://github.com/nguyentruongky/knOtpView.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *