Khi tiêu điểm nhập di chuyển vào hoặc ra khỏi trường văn bản có thể chỉnh sửa, Android sẽ hiển thị hoặc ẩn nội dung nhập — chẳng hạn như bàn phím ảo — như phù hợp. Hệ thống cũng quyết định cách giao diện người dùng và trường văn bản xuất hiện ở trên phương thức nhập. Ví dụ: khi không gian dọc trên màn hình là bị hạn chế, trường văn bản có thể lấp đầy tất cả không gian phía trên phương thức nhập.
Đối với hầu hết ứng dụng, đây là tất cả những hành vi mặc định cần thiết. Trong một số trường hợp, tuy nhiên, bạn có thể muốn kiểm soát nhiều hơn mức hiển thị của phương thức nhập và tác động như thế nào đến bố cục. Bài học này sẽ giải thích cách kiểm soát và ứng phó với chế độ hiển thị của phương thức nhập.
Hiển thị bàn phím mềm khi hoạt động bắt đầu
Mặc dù Android tập trung vào trường văn bản đầu tiên trong bố cục khi khi hoạt động bắt đầu sẽ không hiện bàn phím mềm. Đây là hành vi phù hợp vì việc nhập văn bản có thể không phải là tác vụ chính trong hoạt động. Tuy nhiên, nếu nhập văn bản thực sự là tác vụ chính, chẳng hạn như trên màn hình đăng nhập, thì bạn có thể muốn bàn phím mềm xuất hiện theo mặc định.
Để hiển thị phương thức nhập khi hoạt động của bạn bắt đầu, hãy thêm phương thức
android:windowSoftInputMode
cho thuộc tính
Phần tử <activity>
có giá trị "stateVisible"
. Ví dụ:
<application ... >
<activity
android:windowSoftInputMode="stateVisible" ... >
...
</activity>
...
</application>
Chỉ định cách giao diện người dùng phản hồi
Khi bàn phím mềm xuất hiện trên màn hình, bàn phím sẽ giảm dung lượng có sẵn cho giao diện người dùng của ứng dụng. Hệ thống sẽ quyết định cách điều chỉnh chế độ hiển thị của giao diện người dùng nhưng có thể không chính xác. Để đảm bảo hành vi tốt nhất cho ứng dụng của bạn, hãy chỉ định cách bạn muốn hệ thống hiển thị giao diện người dùng trong dung lượng còn lại.
Để khai báo phương thức xử lý ưu tiên trong một hoạt động, hãy sử dụng phương thức
Thuộc tính android:windowSoftInputMode
trong phần tử <activity>
của tệp kê khai
bằng một trong các nút điều chỉnh giá trị.
Ví dụ: để đảm bảo rằng hệ thống đổi kích thước bố cục của bạn theo
giúp giữ cho tất cả nội dung bố cục đều có thể truy cập được, ngay cả khi
yêu cầu cuộn—sử dụng "adjustResize"
:
<application ... >
<activity
android:windowSoftInputMode="adjustResize" ... >
...
</activity>
...
</application>
Bạn có thể kết hợp thông số kỹ thuật điều chỉnh với bàn phím mềm ban đầu mức độ hiển thị cụ thể từ phần trước:
<activity
android:windowSoftInputMode="stateVisible|adjustResize" ... >
...
</activity>
Việc chỉ định "adjustResize"
là rất quan trọng nếu giao diện người dùng của bạn có các chế độ điều khiển mà
người dùng có thể cần truy cập ngay sau hoặc trong khi thực hiện nhập văn bản. Cho
ví dụ: nếu bạn sử dụng bố cục tương đối để đặt thanh nút ở cuối
màn hình, dùng "adjustResize"
sẽ đổi kích thước bố cục để thanh nút xuất hiện
phía trên bàn phím mềm.
Hiển thị bàn phím mềm theo yêu cầu
Nếu có một phương thức trong vòng đời của hoạt động mà bạn muốn đảm bảo
hiển thị, bạn có thể sử dụng
InputMethodManager
để hiện nội dung.
Ví dụ: phương thức sau đây sẽ lấy
View
mà trong đó người dùng dự kiến sẽ
nhập nội dung nào đó, gọi
requestFocus()
để cung cấp
tiêu điểm, sau đó gọi showSoftInput()
để mở phương thức nhập:
Kotlin
fun showSoftKeyboard(view: View) { if (view.requestFocus()) { val imm = getSystemService(InputMethodManager::class.java) imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT) } }
Java
public void showSoftKeyboard(View view) { if (view.requestFocus()) { InputMethodManager imm = getSystemService(InputMethodManager.class); imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); } }
Hiển thị bàn phím mềm một cách đáng tin cậy
Có một số trường hợp nhất định, chẳng hạn như khi một hoạt động bắt đầu, trong đó
đang dùng InputMethodManager.showSoftInput()
để hiện bàn phím mềm
có thể khiến người dùng không thấy bàn phím phần mềm.
Khả năng hiển thị của bàn phím mềm khi sử dụng showSoftInput()
phụ thuộc vào
về các điều kiện sau:
Khung hiển thị phải được kết nối với bàn phím phần mềm. (Điều này lần lượt là yêu cầu đặt cửa sổ phải làm tâm điểm và trình chỉnh sửa để yêu cầu lấy tiêu điểm khung hiển thị bằng
View.requestFocus()
).Khả năng hiển thị cũng có thể bị ảnh hưởng bởi
android:windowSoftInputMode
và cờ màshowSoftInput()
sử dụng.
Trong một số trường hợp sử dụng, chẳng hạn như khi một hoạt động bắt đầu, một vài
thì không được đáp ứng các điều kiện bắt buộc. Hệ thống không coi chế độ xem này là
kết nối với bàn phím phần mềm, bỏ qua lệnh gọi showSoftInput()
,
và người dùng không thấy bàn phím mềm.
Để đảm bảo bàn phím phần mềm hiển thị một cách đáng tin cậy, bạn có thể sử dụng các cách sau lựa chọn thay thế:
- (Nên dùng) Sử dụng
WindowInsetsControllerCompat
. Đối tượng này hiển thị bàn phím mềm trongActivity.onCreate()
như minh hoạ trong đoạn mã sau. Cuộc gọi sẽ được lên lịch sau thời hạn sẽ được đặt tiêu điểm.
Kotlin
editText.requestFocus() WindowCompat.getInsetsController(window, editText)!!.show(WindowInsetsCompat.Type.ime())
Java
editText.requestFocus(); WindowCompat.getInsetsController(getWindow(), editText).show(WindowInsetsCompat.Type.ime());
- Đăng một tệp có thể chạy. Điều này đảm bảo rằng ứng dụng sẽ chờ cho đến khi nhận được
sự kiện lấy tiêu điểm cửa sổ từ
View.onWindowFocusChanged()
trước khi gọishowSoftInput()
.
Kotlin
class MyEditText : EditText() { ... override fun onWindowFocusChanged(hasWindowFocus: Boolean) { if (hasWindowFocus) { requestFocus() post { val imm: InputMethodManager = getSystemService(InputMethodManager::class.java) imm.showSoftInput(this, 0) } } } }
Java
public class MyEditText extends EditText { ... @Override public void onWindowFocusChanged(boolean hasWindowFocus) { if (hasWindowFocus) { requestFocus(); post(() -> { InputMethodManager imm = getSystemService(InputMethodManager.class); imm.showSoftInput(this, 0); }); } } }
Xử lý cẩn thận các cờ chế độ hiển thị trong thời gian chạy
Khi bật/tắt chế độ hiển thị bàn phím mềm trong thời gian chạy, hãy cẩn thận không truyền một số
gắn cờ các giá trị vào các phương thức này. Ví dụ: nếu ứng dụng mong muốn
bàn phím mềm hiện lên khi gọi
View.getWindowInsetsController().show(ime())
ở Activity.onCreate()
trong khoảng thời gian
hoạt động bắt đầu, nhà phát triển ứng dụng nên thận trọng để không đặt
Cờ SOFT_INPUT_STATE_HIDDEN
hoặc SOFT_INPUT_STATE_ALWAYS_HIDDEN
trong lần đầu khởi chạy để phòng trường hợp bàn phím mềm bị ẩn đột ngột.
Hệ thống thường tự động ẩn bàn phím mềm
Trong hầu hết các trường hợp, hệ thống sẽ xử lý việc ẩn bàn phím mềm. Chiến dịch này có thể là bất kỳ trường hợp nào sau đây:
- Người dùng hoàn tất tác vụ trong trường văn bản.
- Người dùng nhấn phím quay lại hoặc cử chỉ vuốt trong tính năng điều hướng quay lại.
- Người dùng chuyển đến một ứng dụng khác và ứng dụng đó đã đặt
Cờ
SOFT_INPUT_STATE_HIDDEN
hoặcSOFT_INPUT_STATE_ALWAYS_HIDDEN
khi thành phần hiển thị lấy được tiêu điểm.
Ẩn bàn phím mềm theo cách thủ công dựa trên hành vi trước đó của hệ thống
Trong một số trường hợp, ứng dụng của bạn phải ẩn bàn phím mềm theo cách thủ công
ví dụ: khi trường văn bản mất tiêu điểm trong
View.OnFocusChangeListener.onFocusChange
. Hãy thận trọng khi sử dụng kỹ thuật này
; việc đóng bàn phím mềm đột ngột ảnh hưởng xấu đến trải nghiệm người dùng.
Nếu ứng dụng của bạn ẩn bàn phím mềm theo cách thủ công, thì bạn cần biết liệu bàn phím mềm đã được hiển thị rõ ràng hoặc ngầm ẩn:
Bàn phím mềm được coi là đã hiển thị rõ ràng sau một cuộc gọi đến
showSoftInput()
.Ngược lại, bàn phím mềm được xem là đã ngầm hiển thị trong một trong các điều kiện sau:
- Hệ thống đã hiển thị bàn phím mềm trong khi áp dụng
android:windowSoftInputMode
. - Ứng dụng của bạn đã vượt qua
SHOW_IMPLICIT
đếnshowSoftInput()
.
- Hệ thống đã hiển thị bàn phím mềm trong khi áp dụng
Thông thường, hideSoftInputFromWindow()
sẽ ẩn bàn phím mềm bất kể
cách yêu cầu nhưng với HIDE_IMPLICIT_ONLY
bạn chỉ có thể đóng một bàn phím mềm được yêu cầu ngầm.
Hiện hộp thoại hoặc chế độ xem lớp phủ ở trên bàn phím mềm
Trong một số trường hợp, hoạt động của trình chỉnh sửa có thể cần phải tạo một thuộc tính không thể chỉnh sửa hộp thoại hoặc cửa sổ phủ lên trên bàn phím mềm.
Ứng dụng của bạn có một số tuỳ chọn mà các phần sau đây mô tả.
Tóm lại, hãy đảm bảo xử lý chính xác cờ cửa sổ của bàn phím mềm nhắm mục tiêu cửa sổ sao cho đáp ứng các kỳ vọng sau về thứ tự dọc (lớp z):
- Không có cờ (trường hợp thông thường): Phía sau lớp bàn phím mềm và có thể nhận văn bản.
FLAG_NOT_FOCUSABLE
: Ở trên lớp bàn phím mềm, nhưng không thể nhận văn bản.FLAG_ALT_FOCUSABLE_IM
: Ở đầu lớp bàn phím mềm, bạn có thể lấy tiêu điểm nhưng không kết nối với bàn phím mềm. Đồng thời chặn tất cả các chế độ xem bên dưới đó kết nối với bàn phím mềm. Điều này rất hữu ích khi hiển thị hộp thoại ứng dụng không sử dụng văn bản phương thức nhập phía trên lớp bàn phím mềm.FLAG_NOT_FOCUSABLE
vàFLAG_ALT_FOCUSABLE_IM
: Phía sau lớp bàn phím mềm, nhưng không thể nhận văn bản.FLAG_NOT_FOCUSABLE
vàFLAG_NOT_TOUCH_MODAL
: Ở phía trên bàn phím mềm và cho phép "thực hiện" các sự kiện chạm cửa sổ lên bàn phím mềm.
Tạo hộp thoại
Sử dụng FLAG_ALT_FOCUSABLE_IM
cờ cửa sổ hộp thoại để giữ hộp thoại nằm trên bàn phím mềm và để
ngăn bàn phím mềm lấy tiêu điểm:
Kotlin
val content = TextView(this) content.text = "Non-editable dialog on top of soft keyboard" content.gravity = Gravity.CENTER val builder = AlertDialog.Builder(this) .setTitle("Soft keyboard layering demo") .setView(content) mDialog = builder.create() mDialog!!.window!! .addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) mDialog!!.show()
Java
TextView content = new TextView(this); content.setText("Non-editable dialog on top of soft keyboard"); content.setGravity(Gravity.CENTER); final AlertDialog.Builder builder = new AlertDialog.Builder(this) .setTitle("Soft keyboard layering demo") .setView(content); mDialog = builder.create(); mDialog.getWindow().addFlags(FLAG_ALT_FOCUSABLE_IM); mDialog.show();
Tạo chế độ xem lớp phủ
Tạo chế độ xem lớp phủ chỉ định TYPE_APPLICATION_OVERLAY
loại cửa sổ và FLAG_ALT_FOCUSABLE_IM
gắn cờ cửa sổ theo hoạt động được nhắm mục tiêu bằng bàn phím mềm.
Kotlin
val params = WindowManager.LayoutParams( width, /* Overlay window width */ height, /* Overlay window height */ WindowManager.LayoutParams.TYPE_APPLICATION, /* Overlay window type */ WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM /* No need to allow for text input on top of the soft keyboard */ or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, /* Allow touch event send to soft keyboard behind the overlay */ PixelFormat.TRANSLUCENT ) params.title = "Overlay window" mOverlayView!!.layoutParams = params windowManager.addView(mOverlayView, params)
Java
WindowManager.LayoutParams params = new WindowManager.LayoutParams( width, /* Overlay window width */ height, /* Overlay window height */ TYPE_APPLICATION, /* Overlay window type */ FLAG_ALT_FOCUSABLE_IM /* No need to allow for text input on top of the soft keyboard */ | FLAG_NOT_TOUCH_MODAL, /* Allow touch event send to soft keyboard behind the overlay */ PixelFormat.TRANSLUCENT); params.setTitle("Overlay window"); mOverlayView.setLayoutParams(params); getWindowManager().addView(mOverlayView, params);
Hiển thị hộp thoại hoặc chế độ xem bên dưới bàn phím mềm
Ứng dụng của bạn có thể cần tạo một hộp thoại hoặc cửa sổ có các thuộc tính sau:
- Xuất hiện bên dưới bàn phím mềm do hoạt động của trình chỉnh sửa yêu cầu để chữ ký không bị ảnh hưởng bởi việc nhập văn bản.
- Nhận biết được những thay đổi đối với kích thước phần lồng ghép của bàn phím mềm thành điều chỉnh bố cục của cửa sổ hoặc hộp thoại.
Trong trường hợp này, ứng dụng của bạn có một vài lựa chọn. Các phần sau mô tả các lựa chọn này.
Tạo hộp thoại
Tạo hộp thoại bằng cách đặt cả FLAG_NOT_FOCUSABLE
cờ hiệu cho cửa sổ và FLAG_ALT_FOCUSABLE_IM
cờ cho cửa sổ:
Kotlin
val content = TextView(this) content.text = "Non-editable dialog behind soft keyboard" content.gravity = Gravity.CENTER val builder = AlertDialog.Builder(this) .setTitle("Soft keyboard layering demo") .setView(content) mDialog = builder.create() mDialog!!.window!! .addFlags(FLAG_NOT_FOCUSABLE or FLAG_ALT_FOCUSABLE_IM) mDialog!!.show()
Java
TextView content = new TextView(this); content.setText("Non-editable dialog behind soft keyboard"); content.setGravity(Gravity.CENTER); final AlertDialog.Builder builder = new AlertDialog.Builder(this) .setTitle("Soft keyboard layering demo") .setView(content); mDialog = builder.create(); mDialog.getWindow() .addFlags(FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM); mDialog.show();
Tạo chế độ xem lớp phủ
Tạo chế độ xem lớp phủ bằng cách đặt cả FLAG_NOT_FOCUSABLE
cờ hiệu cho cửa sổ và FLAG_ALT_FOCUSABLE_IM
cờ cho cửa sổ:
Kotlin
val params = WindowManager.LayoutParams( width, /* Overlay window width */ height, /* Overlay window height */ WindowManager.LayoutParams.TYPE_APPLICATION, /* Overlay window type */ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, PixelFormat.TRANSLUCENT ) params.title = "Overlay window" mOverlayView!!.layoutParams = params windowManager.addView(mOverlayView, params)
Java
WindowManager.LayoutParams params = new WindowManager.LayoutParams( width, /* Overlay window width */ height, /* Overlay window height */ TYPE_APPLICATION, /* Overlay window type */ FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM, PixelFormat.TRANSLUCENT); params.setTitle("Overlay window"); mOverlayView.setLayoutParams(params); getWindowManager().addView(mOverlayView, params);