78 lines
3.0 KiB
Dart
78 lines
3.0 KiB
Dart
import 'package:flutter/services.dart';
|
||
|
||
class PhoneInputFormatter extends TextInputFormatter {
|
||
@override
|
||
TextEditingValue formatEditUpdate(
|
||
TextEditingValue oldValue,
|
||
TextEditingValue newValue,
|
||
) {
|
||
// Если ввод пустой — возвращаем его как есть
|
||
if (newValue.text.isEmpty) {
|
||
return newValue;
|
||
}
|
||
|
||
// Убираем все нецифровые символы из ввода
|
||
String input = newValue.text.replaceAll(RegExp(r'[^0-9]'), '');
|
||
|
||
// Ограничиваем длину — максимум 11 цифр (без +7)
|
||
if (input.length > 11) {
|
||
input = input.substring(0, 11);
|
||
}
|
||
|
||
// Применяем маску
|
||
String formatted = _applyPhoneMask(input);
|
||
|
||
// Возвращаем отформатированное значение, сохраняя курсор
|
||
return newValue.copyWith(
|
||
text: formatted,
|
||
selection: TextSelection.collapsed(
|
||
offset: _getCursorOffset(input, formatted),
|
||
),
|
||
);
|
||
}
|
||
|
||
// Применяет маску +7 (XXX) XXX-XX-XX
|
||
String _applyPhoneMask(String digits) {
|
||
if (digits.isEmpty) return '';
|
||
if (digits.length == 1) return '+7';
|
||
if (digits.length == 2) return '+7 (${'$digits'.substring(1, 2)})';
|
||
if (digits.length == 3) return '+7 (${digits.substring(1)})';
|
||
if (digits.length == 4) return '+7 (${digits.substring(1, 4)})';
|
||
if (digits.length == 5)
|
||
return '+7 (${digits.substring(1, 4)}) ${digits.substring(4, 5)}';
|
||
if (digits.length == 6)
|
||
return '+7 (${digits.substring(1, 4)}) ${digits.substring(4, 6)}';
|
||
if (digits.length == 7)
|
||
return '+7 (${digits.substring(1, 4)}) ${digits.substring(4, 7)}';
|
||
if (digits.length == 8)
|
||
return '+7 (${digits.substring(1, 4)}) ${digits.substring(4, 7)}-${digits.substring(7, 8)}';
|
||
if (digits.length == 9)
|
||
return '+7 (${digits.substring(1, 4)}) ${digits.substring(4, 7)}-${digits.substring(7, 9)}';
|
||
if (digits.length == 10)
|
||
return '+7 (${digits.substring(1, 4)}) ${digits.substring(4, 7)}-${digits.substring(7, 9)}-${digits.substring(9, 10)}';
|
||
if (digits.length == 11)
|
||
return '+7 (${digits.substring(1, 4)}) ${digits.substring(4, 7)}-${digits.substring(7, 9)}-${digits.substring(9, 11)}';
|
||
|
||
return digits;
|
||
}
|
||
|
||
// Вычисляет новую позицию курсора после форматирования
|
||
int _getCursorOffset(String oldDigits, String formatted) {
|
||
// Если ввод был короче — курсор должен быть в конце
|
||
if (oldDigits.length >= formatted.length) {
|
||
return formatted.length;
|
||
}
|
||
|
||
// Сопоставляем позиции: сколько цифр было до текущей позиции
|
||
int cursorPosition = 0;
|
||
for (int i = 0; i < oldDigits.length; i++) {
|
||
String before = _applyPhoneMask(oldDigits.substring(0, i + 1));
|
||
String after = _applyPhoneMask(oldDigits.substring(0, i + 2));
|
||
if (after.length > before.length) {
|
||
cursorPosition++;
|
||
}
|
||
}
|
||
return cursorPosition;
|
||
}
|
||
}
|