InputFilter là một giao diện Android SDK cho phép chặn và sửa đổi văn bản đầu vào trước khi hiển thị trong EditText. Nhà phát triển đặt ra các quy tắc lọc: ký tự được phép, độ dài tối đa, định dạng đầu vào. Theo Android Developers, 2026, InputFilter được sử dụng để hạn chế nhập chữ cái, chữ số, ký tự đặc biệt và tự động định dạng văn bản. Không giống như TextWatcher, bộ lọc kích hoạt trước khi văn bản thay đổi, ngăn chặn đầu vào không hợp lệ ở cấp độ nguồn.
Những điểm chính
InputFilter là một giao diện chức năng từ gói android.text định nghĩa một phương thức duy nhất filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend). Nó được gọi tự động mỗi khi người dùng cố gắng nhập, dán hoặc thay thế văn bản trong EditText. Giá trị trả về xác định liệu thay đổi sẽ được chấp nhận, từ chối hay sửa đổi.
Mục đích chính của InputFilter là ngăn chặn đầu vào không hợp lệ trước khi văn bản vào trường. Ví dụ: trong trường nhập số điện thoại, bộ lọc có thể chặn chữ cái và ký tự đặc biệt. Trong trường mật khẩu, nó có thể áp đặt độ dài tối thiểu. Trong trường mã xác thực, nó chỉ cho phép chữ số. Không giống như xác thực qua TextWatcher, bộ lọc ngăn các ký tự sai xuất hiện trên màn hình.
Theo Android Developers, InputFilter được sử dụng trong tất cả các thành phần Material Design cho TextInputEditText. Các thư viện như PhoneNumberFormattingTextWatcher kết hợp TextWatcher và InputFilter để định dạng đầy đủ. Nên sử dụng InputFilter như hàng rào bảo vệ đầu tiên chống lại đầu vào không hợp lệ và TextWatcher cho logic bổ sung sau đầu vào.
Phương thức filter nhận sáu tham số: source — văn bản đầu vào, start và end — ranh giới của đoạn đầu vào, dest — nội dung hiện tại của trường, dstart và dend — vị trí chèn. Nếu phương thức trả về null, thay đổi được chấp nhận mà không sửa đổi. Nếu trả về chuỗi rỗng “”, thay đổi bị chặn. Nếu trả về CharSequence mới, văn bản gốc được thay thế bằng giá trị trả về.
Ví dụ: nếu người dùng cố gắng nhập chữ cái “a” vào trường chỉ cho phép chữ số, bộ lọc trả về “” và ký tự không xuất hiện. Nếu nhập “123”, bộ lọc có thể trả về “1-2-3”, thêm dấu phân cách. Cơ chế này cho phép định dạng tự động số điện thoại, ngày tháng và dữ liệu có cấu trúc khác mà không cần TextWatcher.
Quan trọng: InputFilter không sửa đổi nguồn dữ liệu gốc, nó chỉ trả về phiên bản đã lọc. Android tự áp dụng giá trị trả về cho Editable. Nếu bộ lọc trả về null, không cần hành động bổ sung nào. Nếu trả về văn bản đã sửa đổi, Android xóa phạm vi gốc và chèn phạm vi mới.
Android SDK cung cấp một số triển khai tích hợp của InputFilter. Phổ biến nhất là InputFilter.LengthFilter, giới hạn độ dài tối đa của văn bản. Hàm tạo chấp nhận một số nguyên — số ký tự tối đa. Nếu độ dài văn bản hiện tại cộng với đầu vào vượt quá giới hạn, bộ lọc trả về chuỗi bị cắt, ngăn không cho vượt quá giới hạn.
Cũng có sẵn InputFilter.AllCaps, chuyển đổi tất cả ký tự đầu vào thành chữ hoa. Nó được sử dụng trong các trường mã, mã bưu chính và dữ liệu khác mà chữ hoa/thường quan trọng. Bộ lọc không chỉ chặn chữ thường mà còn chuyển đổi chúng, thuận tiện cho người dùng — họ thấy kết quả chuyển đổi.
Có InputFilter.LengthFilter cho nhiều giới hạn — thông qua sự kết hợp các bộ lọc. Ví dụ: nếu bạn cần giới hạn độ dài xuống 20 ký tự và chỉ cho phép chữ số, bạn có thể áp dụng LengthFilter + bộ lọc chữ số tùy chỉnh. Mỗi bộ lọc thực thi tuần tự và kết quả của bộ lọc trước trở thành dest cho bộ lọc tiếp theo.
| Bộ lọc | Mục đích | Ví dụ sử dụng |
|---|---|---|
| LengthFilter | Giới hạn độ dài văn bản | Trường tên tối đa 50 ký tự |
| AllCaps | Chuyển đổi thành chữ hoa | Trường mã bưu chính |
| InputFilter tùy chỉnh | Quy tắc lọc tùy ý | Chỉ chữ số, cấm ký tự đặc biệt |
Để tạo bộ lọc tùy chỉnh, bạn cần triển khai giao diện InputFilter và ghi đè phương thức filter. Một tác vụ phổ biến là bộ lọc chỉ cho phép chữ số. Trong trường hợp này, phương thức kiểm tra từng ký tự từ source bằng Character.isDigit và trả về chuỗi đã lọc hoặc null nếu tất cả ký tự đều hợp lệ.
class DigitsInputFilter : InputFilter {
override fun filter(
source: CharSequence?,
start: Int,
end: Int,
dest: Spanned?,
dstart: Int,
dend: Int
): CharSequence? {
val sb = StringBuilder()
for (i in start until end) {
val c = source?.get(i)
if (c != null && Character.isDigit(c)) {
sb.append(c)
}
}
return if (sb.length == end - start) null else sb
}
}
Ví dụ DigitsInputFilter duyệt qua tất cả ký tự của văn bản đầu vào và chỉ giữ lại chữ số. Nếu tất cả ký tự vượt qua kiểm tra, phương thức trả về null — đây là trường hợp tối ưu vì không yêu cầu thao tác bộ nhớ bổ sung. Nếu một số ký tự bị loại bỏ, một chuỗi mới được trả về và chỉ chữ số đến được EditText.
Một tình huống phổ biến khác là bộ lọc chặn ký tự đặc biệt. Triển khai tương tự: kiểm tra từng ký tự qua Character.isLetterOrDigit hoặc so sánh với danh sách ký tự được phép. Các bộ lọc như vậy được sử dụng trong trường tên người dùng, chuỗi tìm kiếm và những nơi khác mà ký tự đặc biệt không được phép.
Các bộ lọc được đặt trên EditText thông qua phương thức setFilters(InputFilter[]). Mảng bộ lọc thay thế các bộ lọc hiện tại, vì vậy nếu bạn cần thêm bộ lọc vào các bộ lọc hiện có, bạn phải lấy bộ lọc hiện tại qua getFilters(), tạo mảng mới và đặt lại. EditText có một bộ lọc mặc định — LengthFilter, được đặt qua android:maxLength trong XML.
val editText = findViewById<EditText>(R.id.phone_input)
editText.filters = arrayOf(
DigitsInputFilter(),
InputFilter.LengthFilter(10)
)
Trong ví dụ, hai bộ lọc được đặt: DigitsInputFilter (chỉ chữ số) và LengthFilter (tối đa 10 ký tự). Thứ tự bộ lọc trong mảng rất quan trọng: bộ lọc đầu tiên nhận đầu vào gốc, xử lý và chuyển kết quả cho bộ lọc thứ hai. Nếu DigitsInputFilter lọc ra một số ký tự, LengthFilter thấy văn bản đã được lọc và áp dụng giới hạn độ dài lên nó.
Bộ lọc cũng có thể được đặt qua thuộc tính XML android:inputType, tự động thêm một số bộ lọc. Ví dụ: inputType=“phone” thêm DigitsKeyListener và chỉ cho phép chữ số và một số ký tự đặc biệt. Tuy nhiên, để kiểm soát hoàn toàn việc lọc, nên sử dụng setFilters theo chương trình, đặc biệt khi kết hợp nhiều quy tắc.
InputFilter và TextWatcher thực hiện các chức năng khác nhau và thường được sử dụng cùng nhau. InputFilter hoạt động ở cấp độ đầu vào — ngăn các ký tự không hợp lệ vào trường. TextWatcher hoạt động sau đầu vào — cho phép phản ứng với các thay đổi, thực hiện xác thực quy tắc phức tạp và cập nhật giao diện người dùng. Sự kết hợp của cả hai cách tiếp cận mang lại kết quả tốt nhất.
Ví dụ: cho trường nhập email: InputFilter có thể chặn khoảng trắng và ký tự Cyrillic ở cấp độ đầu vào, trong khi TextWatcher có thể kiểm tra tuân thủ đầy đủ mẫu email sau mỗi thay đổi. Cái đầu tiên bảo vệ khỏi các lỗi rõ ràng, cái thứ hai bảo vệ khỏi các lỗi cấu trúc. Sự phân chia trách nhiệm này làm cho mã sạch hơn và giảm tải xác thực.
Theo Material Design Guidelines, bộ lọc nên được áp dụng cho các trường có ràng buộc chặt chẽ: số điện thoại, mã xác thực, mã PIN, mã bưu chính. Đối với các trường có xác thực linh hoạt — tên, địa chỉ, bình luận — chỉ TextWatcher là đủ để không cản trở người dùng nhập các giá trị hợp pháp nhưng không chuẩn.
| Tiêu chí | InputFilter | TextWatcher |
|---|---|---|
| Thời điểm kích hoạt | Trước khi thay đổi văn bản | Sau khi thay đổi văn bản |
| Mục đích | Chặn ký tự không hợp lệ | Phản ứng với thay đổi, xác thực, UI |
| Giá trị trả về | Văn bản đã lọc hoặc null | Không có (void) |
| Áp dụng | setFilters() | addTextChangedListener() |
Câu hỏi thường gặp
InputFilter chặn đầu vào trước khi thay đổi văn bản và có thể chặn hoặc sửa đổi nó. TextWatcher được gọi sau khi thay đổi và cho phép phản ứng với giá trị mới. InputFilter là bảo vệ phòng ngừa, TextWatcher là xử lý sau. Để xác thực biểu mẫu đầy đủ, nên sử dụng cả hai cách tiếp cận.
Truyền một mảng bộ lọc vào phương thức setFilters(). Các bộ lọc thực thi tuần tự theo thứ tự mảng. Để không mất các bộ lọc hiện có, hãy lấy chúng qua getFilters(), thêm bộ lọc mới vào bản sao của mảng và đặt lại qua setFilters. Không ghi đè bộ lọc mà không xem xét các bộ lọc đã được cài đặt.
Có, InputFilter có thể sửa đổi đầu vào bằng cách trả về CharSequence đã sửa đổi. Ví dụ: bộ lọc số điện thoại có thể thêm khoảng trắng hoặc dấu ngoặc. Tuy nhiên, để định dạng phức tạp, tốt hơn nên kết hợp InputFilter với TextWatcher vì bộ lọc tập trung vào việc chặn hơn là xử lý sau.
Bất kỳ ký tự nào: khoảng trắng, chữ cái, chữ số, ký tự đặc biệt, ký tự Unicode. Trong bộ lọc tùy chỉnh, bạn xác định điều kiện bằng Character.isLetter, isDigit, isWhitespace hoặc so sánh với danh sách đen/trắng. Bộ lọc có thể chỉ cho phép Latin, chỉ Cyrillic hoặc chỉ một tập hợp ký tự cụ thể.
Không, InputFilter chỉ kích hoạt khi người dùng nhập hoặc dán từ clipboard. Nếu văn bản được đặt theo chương trình qua setText(), các bộ lọc không được áp dụng. Để kiểm tra văn bản theo chương trình, hãy sử dụng xác thực TextWatcher hoặc kiểm tra rõ ràng trước khi đặt.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm