Trình chỉnh sửa phương thức nhập (IME) là một chế độ kiểm soát người dùng cho phép người dùng nhập văn bản. Android cung cấp khung phương thức nhập có thể mở rộng cho phép các ứng dụng cung cấp cho người dùng các phương thức nhập thay thế, chẳng hạn như bàn phím ảo hoặc nhập liệu bằng lời nói. Sau khi cài đặt IME, người dùng có thể chọn một trong số các chế độ cài đặt hệ thống và sử dụng dữ liệu đó trên toàn bộ hệ thống. Bạn chỉ có thể bật một IME mỗi lần.
Để thêm IME vào hệ thống Android, hãy tạo một ứng dụng Android chứa lớp
mở rộng
InputMethodService
.
Ngoài ra, bạn thường tạo một "chế độ cài đặt" hoạt động chuyển các tuỳ chọn đến dịch vụ IME. Bạn
cũng có thể xác định giao diện người dùng cài đặt được hiển thị trong phần cài đặt hệ thống.
Trang này bao gồm các chủ đề sau:
- Vòng đời IME
- Khai báo thành phần IME trong tệp kê khai ứng dụng
- API IME
- Thiết kế giao diện người dùng IME
- Gửi văn bản từ IME đến ứng dụng
- Làm việc với các loại phụ của IME
- Những điểm khác cần cân nhắc về IME
Nếu bạn chưa từng làm việc với IME, hãy đọc bài viết giới thiệu Phương thức nhập trên màn hình đầu tiên.
Vòng đời IME
Sơ đồ dưới đây mô tả vòng đời của một IME:
![Hình ảnh minh hoạ vòng đời của một IME.](https://developer.android.com/static/resources/articles/images/inputmethod_lifecycle_image.png?authuser=0000&hl=vi)
Các phần sau đây mô tả cách triển khai giao diện người dùng và mã liên kết với một IME đều tuân theo vòng đời này.
Khai báo thành phần của IME trong tệp kê khai
Trong hệ thống Android, IME là một ứng dụng Android có chứa dịch vụ IME đặc biệt. Chiến lược phát hành đĩa đơn
tệp kê khai của ứng dụng phải khai báo dịch vụ, yêu cầu các quyền cần thiết, cung cấp
bộ lọc ý định khớp với hành động action.view.InputMethod
và cung cấp siêu dữ liệu
xác định các đặc điểm của IME. Ngoài ra, việc cung cấp giao diện cài đặt cho phép
sửa đổi hành vi của IME, bạn có thể xác định chế độ "cài đặt" hoạt động có thể được khởi chạy từ
Cài đặt hệ thống.
Đoạn mã sau đây khai báo dịch vụ IME. Ứng dụng yêu cầu quyền
BIND_INPUT_METHOD
để cho phép dịch vụ kết nối IME với hệ thống, hãy thiết lập bộ lọc ý định khớp với hành động
android.view.InputMethod
và xác định siêu dữ liệu cho IME:
<!-- Declares the input method service. --> <service android:name="FastInputIME" android:label="@string/fast_input_label" android:permission="android.permission.BIND_INPUT_METHOD"> <intent-filter> <action android:name="android.view.InputMethod" /> </intent-filter> <meta-data android:name="android.view.im" android:resource="@xml/method" /> </service>
Đoạn mã tiếp theo khai báo hoạt động cài đặt cho IME. Có bộ lọc ý định cho
ACTION_MAIN
mà
cho biết hoạt động này là điểm truy cập chính cho ứng dụng IME:
<!-- Optional: an activity for controlling the IME settings. --> <activity android:name="FastInputIMESettings" android:label="@string/fast_input_settings"> <intent-filter> <action android:name="android.intent.action.MAIN"/> </intent-filter> </activity>
Bạn cũng có thể cung cấp quyền truy cập vào các chế độ cài đặt của IME trực tiếp từ giao diện người dùng.
API phương thức nhập
Bạn có thể tìm thấy các lớp dành riêng cho IME trong
android.inputmethodservice
và
android.view.inputmethod
. Lớp KeyEvent
là
rất quan trọng để xử lý các ký tự trên bàn phím.
Phần trung tâm của IME là một thành phần dịch vụ — một lớp mở rộng
InputMethodService
. Ngoài việc triển khai vòng đời dịch vụ thông thường,
có các lệnh gọi lại để cung cấp giao diện người dùng của IME, xử lý hoạt động đầu vào của người dùng và gửi văn bản đến
có tiêu điểm. Theo mặc định, lớp InputMethodService
cung cấp hầu hết
quá trình triển khai để quản lý trạng thái và chế độ hiển thị của IME cũng như giao tiếp với
trường nhập dữ liệu.
Các lớp sau đây cũng quan trọng:
BaseInputConnection
-
Xác định kênh liên lạc từ một
InputMethod
quay lại ứng dụng đang nhận thông tin đầu vào. Bạn sử dụng nó để đọc văn bản xung quanh con trỏ, chuyển văn bản vào hộp văn bản và gửi các sự kiện chính thô đến ứng dụng. Ứng dụng phải mở rộng lớp này thay vì triển khai giao diện cơ sởInputConnection
. KeyboardView
-
Phần mở rộng của
View
hiển thị bàn phím và phản hồi các sự kiện nhập của người dùng. Bố cục bàn phím được chỉ định bằng bản sao củaKeyboard
, mà bạn có thể xác định trong tệp XML.
Thiết kế giao diện người dùng cho phương thức nhập
Có hai phần tử hình ảnh chính cho IME: khung hiển thị input (đầu vào) và chế độ xem đề xuất. Bạn chỉ phải triển khai các yếu tố liên quan đến mà bạn đang thiết kế.
Chế độ xem nhập dữ liệu
Khung hiển thị nhập dữ liệu là giao diện người dùng nơi người dùng nhập văn bản dưới dạng gõ phím, viết tay hoặc
cử chỉ. Khi IME hiển thị lần đầu tiên, hệ thống sẽ gọi hàm
onCreateInputView()
. Trong quá trình triển khai phương thức này, hãy tạo bố cục mà bạn muốn hiển thị trong IME
cửa sổ và trả về bố cục cho hệ thống. Đoạn mã sau đây cho thấy một ví dụ về cách triển khai
phương thức onCreateInputView()
:
Kotlin
override fun onCreateInputView(): View { return layoutInflater.inflate(R.layout.input, null).apply { if (this is MyKeyboardView) { setOnKeyboardActionListener(this@MyInputMethod) keyboard = latinKeyboard } } }
Java
@Override public View onCreateInputView() { MyKeyboardView inputView = (MyKeyboardView) getLayoutInflater().inflate(R.layout.input, null); inputView.setOnKeyboardActionListener(this); inputView.setKeyboard(latinKeyboard); return inputView; }
Trong ví dụ này, MyKeyboardView
là một thực thể của cách triển khai tuỳ chỉnh của
KeyboardView
kết xuất Keyboard
.
Chế độ xem đề xuất
Chế độ xem đề xuất là giao diện người dùng trong đó IME hiển thị nội dung chỉnh sửa hoặc đề xuất từ có thể có
để người dùng chọn. Trong vòng đời IME, hệ thống gọi
onCreateCandidatesView()
khi đã sẵn sàng hiển thị khung hiển thị đề xuất. Trong quá trình triển khai phương thức này, hãy trả về một
hiển thị các đề xuất từ hoặc trả về giá trị rỗng nếu bạn không muốn hiển thị bất kỳ nội dung nào. Giá trị rỗng
là hành vi mặc định, vì vậy, bạn không phải triển khai thuộc tính này nếu không cung cấp
nội dung đề xuất.
Những điều cần cân nhắc khi thiết kế giao diện người dùng
Phần này mô tả một số cân nhắc về thiết kế giao diện người dùng cho IME.
Xử lý nhiều kích thước màn hình
Giao diện người dùng cho IME của bạn phải có khả năng điều chỉnh tỷ lệ cho nhiều kích thước màn hình và xử lý được cả hai chiều ngang và hướng dọc. Ở chế độ IME không toàn màn hình, hãy chừa đủ khoảng trống để ứng dụng hiển thị trường văn bản và mọi ngữ cảnh liên quan sao cho không quá một nửa màn hình bị chiếm IME. Ở chế độ IME toàn màn hình, đây không phải là vấn đề.
Xử lý nhiều loại dữ liệu đầu vào
Trường văn bản Android cho phép bạn đặt một loại dữ liệu nhập cụ thể, chẳng hạn như văn bản dạng tự do, số, URL, địa chỉ email và chuỗi tìm kiếm. Khi bạn triển khai một IME mới, hãy phát hiện loại dữ liệu đầu vào của mỗi IME và cung cấp giao diện thích hợp cho trường đó. Tuy nhiên, bạn không phải thiết lập IME để kiểm tra xem người dùng có nhập văn bản hợp lệ cho loại đầu vào không. Đây là trách nhiệm của ứng dụng sở hữu trường văn bản.
Ví dụ: đây là giao diện mà IME tiếng Latinh cung cấp cho văn bản trên nền tảng Android đầu vào:
![Hình ảnh hiển thị dữ liệu đã nhập văn bản trên một IME tiếng Latinh](https://developer.android.com/static/images/ui/text_input.png?authuser=0000&hl=vi)
Đây là giao diện mà IME Latinh cung cấp cho nền tảng Android đầu vào dạng số:
![Hình ảnh hiển thị một dữ liệu đầu vào dạng số trên một IME tiếng Latinh](https://developer.android.com/static/images/ui/numeric_input.png?authuser=0000&hl=vi)
Khi một trường nhập dữ liệu nhận được tiêu điểm và IME của bạn khởi động, hệ thống sẽ gọi
onStartInputView()
,
đang truyền một giá trị
Đối tượng EditorInfo
chứa thông tin chi tiết về loại dữ liệu đầu vào và các thuộc tính khác của trường văn bản. Trong đối tượng này,
thời gian
inputType
chứa loại dữ liệu đầu vào của trường văn bản.
Trường inputType
là một int
có chứa các mẫu bit cho nhiều
cài đặt loại phương thức nhập. Để kiểm tra trường đó cho loại dữ liệu đầu vào của trường văn bản, hãy che trường đó bằng hằng số
TYPE_MASK_CLASS
,
như sau:
Kotlin
inputType and InputType.TYPE_MASK_CLASS
Java
inputType & InputType.TYPE_MASK_CLASS
Mẫu bit loại dữ liệu đầu vào có thể có một trong các giá trị sau:
TYPE_CLASS_NUMBER
- Một trường văn bản để nhập số. Như minh hoạ trong hình 3, IME tiếng Latinh hiển thị một bàn phím số cho các trường thuộc loại này.
TYPE_CLASS_DATETIME
- Trường văn bản để nhập ngày và giờ.
TYPE_CLASS_PHONE
- Một trường văn bản để nhập số điện thoại.
TYPE_CLASS_TEXT
- Một trường văn bản để nhập ký tự bất kỳ được hỗ trợ.
Các hằng số này được mô tả chi tiết hơn trong tài liệu tham khảo về
InputType
.
Trường inputType
có thể chứa các bit khác cho biết một biến thể của trường văn bản
loại, chẳng hạn như:
TYPE_TEXT_VARIATION_PASSWORD
- Một biến thể của
TYPE_CLASS_TEXT
để nhập mật khẩu. Phương thức nhập sẽ xuất hiện in hình dơi thay vì văn bản thực tế. TYPE_TEXT_VARIATION_URI
- Một biến thể của
TYPE_CLASS_TEXT
để nhập URL của trang web và các Tài nguyên thống nhất khác Giá trị nhận dạng (URI). TYPE_TEXT_FLAG_AUTO_COMPLETE
- Một biến thể của
TYPE_CLASS_TEXT
để nhập văn bản mà ứng dụng tự động hoàn thành từ từ điển, nội dung tìm kiếm hoặc công cụ khác.
Hãy che inputType
bằng hằng số thích hợp khi bạn kiểm thử các biến thể này. Chiến lược phát hành đĩa đơn
các hằng số mặt nạ hiện có được liệt kê trong tài liệu tham khảo về InputType
.
Gửi văn bản đến ứng dụng
Khi người dùng nhập văn bản bằng IME, bạn có thể gửi văn bản đến ứng dụng bằng cách gửi
các sự kiện chính hoặc bằng cách chỉnh sửa văn bản xung quanh con trỏ trong trường văn bản của ứng dụng. Trong cả hai trường hợp,
sử dụng một thực thể của InputConnection
để gửi văn bản. Để nhận phiên bản này, hãy gọi
InputMethodService.getCurrentInputConnection()
.
Chỉnh sửa văn bản quanh con trỏ
Khi bạn xử lý việc chỉnh sửa văn bản hiện có, một số phương pháp hữu ích trong
BaseInputConnection
như sau:
-
getTextBeforeCursor()
- Trả về một
CharSequence
chứa số ký tự được yêu cầu trước vị trí con trỏ hiện tại. -
getTextAfterCursor()
- Trả về
CharSequence
chứa số ký tự được yêu cầu sau vị trí hiện tại của con trỏ. -
deleteSurroundingText()
- Xoá số ký tự chỉ định trước và sau vị trí con trỏ hiện tại.
-
commitText()
- Xác nhận
CharSequence
vào trường văn bản và đặt vị trí con trỏ mới.
Ví dụ: đoạn mã sau đây cho biết cách thay thế bốn ký tự ở bên trái của thẻ con trỏ có nội dung "Hello!":
Kotlin
currentInputConnection.also { ic: InputConnection -> ic.deleteSurroundingText(4, 0) ic.commitText("Hello", 1) ic.commitText("!", 1) }
Java
InputConnection ic = getCurrentInputConnection(); ic.deleteSurroundingText(4, 0); ic.commitText("Hello", 1); ic.commitText("!", 1);
Hỗ trợ soạn văn bản trước khi gửi
Nếu IME của bạn dự đoán văn bản hoặc yêu cầu nhiều bước để soạn một ký tự hoặc từ, bạn có thể hiển thị
trong trường văn bản cho đến khi người dùng nhập từ, sau đó bạn có thể thay thế các phần
cấu trúc với văn bản hoàn chỉnh. Bạn có thể xử lý đặc biệt cho văn bản bằng cách thêm
span vào tệp đó khi bạn truyền hàm đó đến
setComposingText()
.
Đoạn mã sau đây minh hoạ cách hiển thị tiến trình trong một trường văn bản:
Kotlin
currentInputConnection.also { ic: InputConnection -> ic.setComposingText("Composi", 1) ic.setComposingText("Composin", 1) ic.commitText("Composing ", 1) }
Java
InputConnection ic = getCurrentInputConnection(); ic.setComposingText("Composi", 1); ic.setComposingText("Composin", 1); ic.commitText("Composing ", 1);
Chặn sự kiện liên quan đến phím cứng
Mặc dù cửa sổ phương thức nhập không có tiêu điểm rõ ràng nhưng cửa sổ này nhận được các sự kiện liên quan đến phím phần cứng trước tiên và có thể sử dụng hoặc chuyển tiếp chúng đến ứng dụng. Ví dụ: bạn có thể muốn sử dụng các phím định hướng để điều hướng trong giao diện người dùng nhằm lựa chọn đề xuất trong quá trình soạn. Bạn cũng nên giữ phím quay lại để đóng mọi hộp thoại bắt nguồn từ phương thức nhập cửa sổ.
Để chặn phím phần cứng, hãy ghi đè
onKeyDown()
và
onKeyUp()
Gọi phương thức super()
cho các khoá mà bạn không muốn tự xử lý.
Tạo loại phụ IME
Các loại phụ cho phép IME hiển thị nhiều chế độ nhập và ngôn ngữ được IME hỗ trợ. Loại phụ có thể đại diện như sau:
- Ngôn ngữ, chẳng hạn như en_US hoặc fr_FR
- Chế độ nhập, chẳng hạn như giọng nói, bàn phím hoặc chữ viết tay
- Các kiểu nhập, biểu mẫu hoặc thuộc tính khác dành riêng cho IME, chẳng hạn như phím 10 phím hoặc QWERTY bố cục bàn phím
Chế độ này có thể là văn bản bất kỳ, chẳng hạn như "bàn phím" hoặc "giọng nói". Loại phụ cũng có thể hiển thị kết hợp trong số này.
Thông tin loại phụ được dùng cho hộp thoại trình chuyển đổi IME có trên thanh thông báo và đối với chế độ cài đặt IME. Thông tin này cũng cho phép khung hiển thị một loại phụ cụ thể của IME trực tiếp. Khi bạn tạo IME, hãy sử dụng tiện ích loại phụ vì tiện ích này giúp người dùng xác định và chuyển đổi giữa các ngôn ngữ và chế độ IME.
Xác định các loại phụ tại một trong các tệp tài nguyên XML của phương thức nhập bằng cách sử dụng
Phần tử <subtype>
. Đoạn mã sau đây xác định một IME có hai loại phụ: một
loại bàn phím phụ cho ngôn ngữ tiếng Anh (Mỹ) và loại bàn phím phụ khác cho tiếng Pháp
ngôn ngữ cho Pháp:
<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="com.example.softkeyboard.Settings" android:icon="@drawable/ime_icon"> <subtype android:name="@string/display_name_english_keyboard_ime" android:icon="@drawable/subtype_icon_english_keyboard_ime" android:languageTag="en-US" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="somePrivateOption=true" /> <subtype android:name="@string/display_name_french_keyboard_ime" android:icon="@drawable/subtype_icon_french_keyboard_ime" android:languageTag="fr-FR" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="someVariable=30,someInternalOption=false" /> <subtype android:name="@string/display_name_german_keyboard_ime" ... /> </input-method>
Để đảm bảo các loại phụ được gắn nhãn chính xác trong giao diện người dùng, hãy sử dụng `%s` để lấy nhãn loại phụ giống với nhãn ngôn ngữ của loại phụ. Điều này được minh hoạ trong hai đoạn mã tiếp theo. Chiến lược phát hành đĩa đơn đoạn mã đầu tiên cho thấy một phần tệp XML của phương thức nhập:
<subtype android:label="@string/label_subtype_generic" android:imeSubtypeLocale="en_US" android:icon="@drawable/icon_en_us" android:imeSubtypeMode="keyboard" />
Đoạn mã tiếp theo là một phần của tệp strings.xml
của IME. Tài nguyên chuỗi
label_subtype_generic
, được dùng theo định nghĩa giao diện người dùng của phương thức nhập để đặt giá trị
của loại phụ, được xác định như sau:
<string name="label_subtype_generic">%s</string>
Chế độ cài đặt này giúp tên hiển thị của loại phụ khớp với chế độ cài đặt ngôn ngữ. Ví dụ: trong bất kỳ Ngôn ngữ tiếng Anh, tên hiển thị là "Tiếng Anh (Hoa Kỳ)".
Chọn loại phụ IME từ thanh thông báo
Hệ thống Android quản lý mọi loại phụ mà mọi IME hiển thị. Loại phụ IME được coi là các chế độ IME thuộc về chúng. Người dùng có thể điều hướng từ thanh thông báo hoặc ứng dụng Cài đặt đến trình đơn các loại phụ IME có sẵn, như trong hình sau:
![Hình ảnh minh hoạ Ngôn ngữ và nhập trình đơn Hệ thống](https://developer.android.com/static/images/ui/languages_and_input.png?authuser=0000&hl=vi)
Chọn loại phụ IME từ phần Cài đặt hệ thống
Người dùng cũng có thể kiểm soát cách sử dụng các loại phụ trong Ngôn ngữ và bảng cài đặt phương thức nhập trong phần cài đặt hệ thống:
![Hình ảnh hiển thị trình đơn chọn Ngôn ngữ](https://developer.android.com/static/images/ui/languages.png?authuser=0000&hl=vi)
Chuyển đổi giữa các loại phụ IME
Bạn có thể cho phép người dùng dễ dàng chuyển đổi giữa các loại phụ của IME bằng cách cung cấp một phím chuyển đổi, chẳng hạn như biểu tượng ngôn ngữ hình địa cầu trên bàn phím. Điều này giúp nâng cao khả năng sử dụng của bàn phím và thuận tiện cho người dùng. Để bật tính năng chuyển đổi này, hãy thực hiện các bước sau:
- Khai báo
supportsSwitchingToNextInputMethod = "true"
trong tệp tài nguyên XML của phương thức nhập. Nội dung khai báo của bạn phải giống với đoạn mã sau:<input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="com.example.softkeyboard.Settings" android:icon="@drawable/ime_icon" android:supportsSwitchingToNextInputMethod="true">
- Gọi
shouldOfferSwitchingToNextInputMethod()
. - Nếu phương thức trả về true (đúng), hãy hiển thị phím chuyển đổi.
- Khi người dùng nhấn vào phím chuyển đổi, hãy gọi
switchToNextInputMethod()
, truyền giá trị false. Giá trị false sẽ yêu cầu hệ thống xử lý tất cả các loại phụ như nhau, bất kể họ thuộc IME nào. Việc chỉ định đúng sẽ yêu cầu hệ thống chuyển đổi qua các loại phụ trong IME hiện tại.
Lưu ý chung về IME
Sau đây là một số yếu tố khác cần cân nhắc khi triển khai IME:
- Cung cấp cho người dùng cách để đặt các tuỳ chọn trực tiếp từ giao diện người dùng của IME.
- Đưa ra cách để người dùng chuyển sang một IME khác trực tiếp từ giao diện người dùng phương thức nhập, vì có thể bạn đã cài đặt nhiều IME trên thiết bị.
- Hiển thị nhanh giao diện người dùng của IME. Tải trước hoặc tải theo yêu cầu bất kỳ tài nguyên lớn nào để người dùng thấy IME ngay khi nhấn vào trường văn bản. Lưu tài nguyên và chế độ xem vào bộ nhớ đệm để lưu các lời gọi phương thức nhập.
- Giải phóng các cơ cấu phân bổ bộ nhớ lớn ngay sau khi ẩn cửa sổ phương thức nhập để để ứng dụng có đủ bộ nhớ để chạy. Sử dụng thông báo trì hoãn để phát hành tài nguyên nếu IME bị ẩn trong vài giây.
- Đảm bảo người dùng có thể nhập nhiều ký tự nhất có thể cho ngôn ngữ hoặc ngôn ngữ đó được liên kết với IME. Người dùng có thể sử dụng dấu câu trong mật khẩu hoặc tên người dùng, vì vậy, IME của bạn phải cung cấp nhiều ký tự khác nhau để cho phép người dùng nhập mật khẩu và truy cập vào thiết bị.