เมื่อโฟกัสอินพุตย้ายเข้าหรือออกจากฟิลด์ข้อความที่แก้ไขได้ Android จะแสดงหรือ ซ่อนการป้อนข้อมูล เช่น แป้นพิมพ์บนหน้าจอ เช่น เหมาะสม ระบบจะกำหนดการแสดง UI และช่องข้อความที่ด้านบนด้วย วิธีการป้อนข้อมูล ตัวอย่างเช่น เมื่อพื้นที่แนวตั้งบนหน้าจอ ช่องข้อความอาจเต็มพื้นที่เหนือวิธีการป้อนข้อมูล
ซึ่งแอปส่วนใหญ่จำเป็นต้องใช้ลักษณะการทำงานเริ่มต้นเหล่านี้ ในบางกรณี แต่คุณอาจต้องการควบคุมการมองเห็นวิธีการป้อนข้อมูลมากขึ้นและ ผลกระทบต่อเลย์เอาต์ บทเรียนนี้อธิบายวิธีควบคุมและตอบสนองต่อ ระดับการเข้าถึงวิธีการป้อนข้อมูล
แสดงแป้นพิมพ์เมื่อกิจกรรมเริ่มขึ้น
แม้ว่า Android จะให้ความสำคัญกับช่องข้อความฟิลด์แรกในการจัดวางของคุณเมื่อ กิจกรรมเริ่มขึ้น ระบบจะไม่แสดงแป้นพิมพ์เสมือน พฤติกรรมนี้เหมาะสม เพราะการป้อนข้อความอาจไม่ใช่งานหลักในกิจกรรม อย่างไรก็ตาม หาก จริงๆ แล้วการป้อนข้อความเป็นงานหลัก เช่น ในหน้าจอการเข้าสู่ระบบ อาจต้องการให้แป้นพิมพ์ปรากฏขึ้นเป็นค่าเริ่มต้น
หากต้องการแสดงวิธีป้อนข้อมูลเมื่อกิจกรรมเริ่มต้น ให้เพิ่มพารามิเตอร์
android:windowSoftInputMode
ลงในแอตทริบิวต์
องค์ประกอบ <activity>
ที่มีค่า "stateVisible"
เช่น
<application ... >
<activity
android:windowSoftInputMode="stateVisible" ... >
...
</activity>
...
</application>
ระบุว่าจะให้ UI ตอบสนองอย่างไร
เมื่อแป้นพิมพ์เสมือนปรากฏขึ้นบนหน้าจอ จะเป็นการลดขนาดพื้นที่ พร้อมใช้งานสำหรับ UI ของแอป ระบบจะเลือกวิธีปรับการแสดงผล ของ UI ได้ แต่อาจไม่ถูกต้อง เพื่อให้ได้ลักษณะการทำงานที่ดีที่สุด สำหรับแอปของคุณ ให้ระบุวิธีที่คุณต้องการให้ระบบแสดง UI ใน ที่เหลืออยู่
หากต้องการประกาศการรักษาที่ต้องการในกิจกรรม ให้ใช้
แอตทริบิวต์ android:windowSoftInputMode
ในองค์ประกอบ <activity>
ของไฟล์ Manifest
โดยใช้ปุ่ม "ปรับราคาเสนอ" อันใดอันหนึ่ง
ตัวอย่างเช่น เพื่อให้มั่นใจว่าระบบจะปรับขนาดการออกแบบของคุณให้เป็นขนาดที่พร้อมใช้งาน
โดยอัตโนมัติ ซึ่งทำให้เข้าถึงเนื้อหาเลย์เอาต์ทั้งหมดของคุณได้ แม้ว่า
ต้องเลื่อน ให้ใช้ "adjustResize"
:
<application ... >
<activity
android:windowSoftInputMode="adjustResize" ... >
...
</activity>
...
</application>
คุณสามารถรวมข้อกำหนดการปรับโดยใช้แป้นพิมพ์เสมือนเริ่มต้นได้ การแสดงผลจากส่วนก่อนหน้า:
<activity
android:windowSoftInputMode="stateVisible|adjustResize" ... >
...
</activity>
การระบุ "adjustResize"
เป็นสิ่งสำคัญหาก UI ของคุณมีการควบคุมที่
ผู้ใช้อาจต้องเข้าถึงเว็บไซต์ทันทีหลังจากหรือขณะป้อนข้อความ สำหรับ
ตัวอย่างเช่น หากคุณใช้เค้าโครงที่สัมพันธ์กันเพื่อวางแถบปุ่มที่ด้านล่างของ
หน้าจอโดยใช้ "adjustResize"
ปรับขนาดเลย์เอาต์เพื่อให้แถบปุ่มปรากฏขึ้น
เหนือแป้นพิมพ์เสมือน
แสดงแป้นพิมพ์เสมือนตามคำขอ
หากมีเมธอดในวงจรของกิจกรรมซึ่งคุณต้องการตรวจสอบว่า
แสดงวิธีการป้อนข้อมูล
InputMethodManager
เพื่อแสดง
ตัวอย่างเช่น วิธีการต่อไปนี้ใช้
View
ที่คาดว่าผู้ใช้จะ
พิมพ์บางอย่าง, โทร
requestFocus()
ที่จะให้
จากนั้นโฟกัสจะเรียก showSoftInput()
เพื่อเปิดวิธีการป้อนข้อมูล
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); } }
แสดงแป้นพิมพ์อย่างมีประสิทธิภาพ
ในบางสถานการณ์ เช่น เมื่อกิจกรรมเริ่มขึ้น
ใช้ InputMethodManager.showSoftInput()
เพื่อแสดงแป้นพิมพ์เสมือน
อาจทำให้ผู้ใช้มองไม่เห็นแป้นพิมพ์ซอฟต์แวร์
การมองเห็นแป้นพิมพ์เสมือนเมื่อใช้ showSoftInput()
จะเชื่อถือได้
ในเงื่อนไขต่อไปนี้
โดยมุมมองต้องเชื่อมต่อกับซอฟต์แวร์แป้นพิมพ์อยู่แล้ว (ซึ่งก็จะทำให้ ต้องโฟกัสหน้าต่างและเครื่องมือแก้ไข ดูเพื่อขอโฟกัสมุมมองกับ
View.requestFocus()
)ระดับการเข้าถึงอาจได้รับผลกระทบจาก
android:windowSoftInputMode
ด้วย และแฟล็กที่showSoftInput()
ใช้
ในบางกรณีการใช้งาน เช่น เมื่อกิจกรรมเริ่มขึ้น บางกรณี
ไม่ตรงตามเงื่อนไขที่กำหนด ระบบไม่พิจารณาการดูเป็น
เชื่อมต่อกับแป้นพิมพ์ซอฟต์แวร์อยู่ ไม่ต้องสนใจการเรียก showSoftInput()
และผู้ใช้จะมองไม่เห็นแป้นพิมพ์เสมือน
หากต้องการตรวจสอบว่าซอฟต์แวร์แป้นพิมพ์แสดงขึ้นมาอย่างถูกต้อง คุณสามารถใช้สิ่งต่อไปนี้ ทางเลือก:
- (แนะนำ) ใช้
WindowInsetsControllerCompat
วัตถุนี้ แสดงแป้นพิมพ์เสมือนในระหว่างActivity.onCreate()
ตามที่แสดงใน โค้ดต่อไปนี้ เรารับประกันว่าการโทรจะถึงกำหนดเวลาหลังจากกรอบเวลาดังกล่าว ให้ความสนใจ
Kotlin
editText.requestFocus() WindowCompat.getInsetsController(window, editText)!!.show(WindowInsetsCompat.Type.ime())
Java
editText.requestFocus(); WindowCompat.getInsetsController(getWindow(), editText).show(WindowInsetsCompat.Type.ime());
- โพสต์การเรียกใช้ได้ ซึ่งจะช่วยให้มั่นใจว่าแอปจะรอจนกว่าจะได้รับ
เหตุการณ์โฟกัสในหน้าต่างจาก
View.onWindowFocusChanged()
ก่อนโทรshowSoftInput()
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); }); } } }
จัดการแฟล็กระดับการเข้าถึงรันไทม์อย่างระมัดระวัง
เมื่อสลับการแสดงแป้นพิมพ์แบบนุ่มนวลขณะรันไทม์ โปรดระมัดระวังอย่าข้าม
แจ้งค่าลงในวิธีการเหล่านี้ ตัวอย่างเช่น หากแอปพลิเคชันคาดว่า
แป้นพิมพ์เสมือนแสดงขึ้นเมื่อโทร
View.getWindowInsetsController().show(ime())
ใน Activity.onCreate()
ระหว่าง
กิจกรรมเริ่มขึ้น นักพัฒนาแอปพลิเคชันควรระวังอย่าตั้งค่า
การแจ้ง SOFT_INPUT_STATE_HIDDEN
หรือ SOFT_INPUT_STATE_ALWAYS_HIDDEN
ในช่วงการเปิดครั้งแรก ในกรณีที่ซอฟต์แป้นพิมพ์ซ่อนอยู่โดยไม่คาดคิด
โดยปกติแล้วระบบจะซ่อนแป้นพิมพ์เสมือนโดยอัตโนมัติ
โดยส่วนใหญ่ ระบบจะจัดการกับการซ่อนแป้นพิมพ์เสมือน ช่วงเวลานี้ อาจเป็นกรณีใดกรณีหนึ่งต่อไปนี้
- ผู้ใช้ดำเนินการดังกล่าวเสร็จแล้วในช่องข้อความ
- ผู้ใช้กดปุ่มย้อนกลับหรือท่าทางสัมผัสการปัดเมื่อใช้การนำทางกลับ
- ผู้ใช้ไปยังแอปอื่นและที่แอปอื่นตั้งค่าไว้
แฟล็ก
SOFT_INPUT_STATE_HIDDEN
หรือSOFT_INPUT_STATE_ALWAYS_HIDDEN
เมื่อมุมมองได้โฟกัส
ซ่อนแป้นพิมพ์เสมือนด้วยตนเองตามลักษณะการทำงานก่อนหน้านี้ของระบบ
แอปของคุณต้องซ่อนแป้นพิมพ์เสมือนด้วยตนเองในบางสถานการณ์
ตัวอย่างเช่น เมื่อฟิลด์ข้อความหายไป
View.OnFocusChangeListener.onFocusChange
ใช้เทคนิคนี้อย่างรอบคอบ
การปิดซอฟต์แป้นพิมพ์จะทำให้ประสบการณ์ของผู้ใช้แย่ลงโดยไม่คาดคิด
หากแอปซ่อนแป้นพิมพ์เสมือนด้วยตนเอง คุณจำเป็นต้องทราบว่า แป้นพิมพ์เสมือนแสดงอย่างชัดแจ้งหรือโดยนัย
แป้นพิมพ์เสมือนถือว่าแสดงอย่างชัดแจ้งหลังจาก โทรหา
showSoftInput()
ในทางกลับกัน แป้นพิมพ์เสมือนถือว่าแสดงโดยปริยายใน เงื่อนไขใดเงื่อนไขหนึ่งต่อไปนี้
- ระบบแสดงแป้นพิมพ์เสมือนขณะที่กด
android:windowSoftInputMode
- แอปของคุณสอบผ่าน
SHOW_IMPLICIT
showSoftInput()
- ระบบแสดงแป้นพิมพ์เสมือนขณะที่กด
โดยปกติแล้ว hideSoftInputFromWindow()
จะซ่อนแป้นพิมพ์เสมือนโดยไม่คำนึงถึง
ตามที่ขอ แต่ใช้ HIDE_IMPLICIT_ONLY
จะจำกัดเพียงการปิดแป้นพิมพ์เสมือนที่ขอโดยนัยได้
แสดงกล่องโต้ตอบหรือมุมมองซ้อนทับที่ด้านบนของแป้นพิมพ์เสมือน
ในบางสถานการณ์ กิจกรรมตัวแก้ไขอาจต้องสร้าง URL ที่แก้ไขไม่ได้ กล่องโต้ตอบหรือหน้าต่างวางซ้อนที่ด้านบนของแป้นพิมพ์เสมือน
แอปของคุณมีตัวเลือก 2-3 อย่าง ซึ่งอธิบายไว้ในส่วนต่อไปนี้
โดยสรุปแล้ว โปรดตรวจสอบว่าได้จัดการธงหน้าต่างของแป้นพิมพ์เสมือนอย่างถูกต้อง การกำหนดเป้าหมายกรอบเวลาดังกล่าว ให้เป็นไปตามความคาดหวังต่อไปนี้ เกี่ยวกับการจัดลำดับในแนวตั้ง (ชั้น Z) ดังต่อไปนี้
- ไม่มีธง (ตัวพิมพ์ปกติ): อยู่ด้านหลังชั้นแป้นพิมพ์เสมือนและรับข้อความได้
FLAG_NOT_FOCUSABLE
: อยู่ด้านบนของเลเยอร์แป้นพิมพ์เสมือน แต่ไม่สามารถรับข้อความได้FLAG_ALT_FOCUSABLE_IM
: ที่ด้านบนของเลเยอร์แป้นพิมพ์เสมือนสามารถโฟกัสได้ แต่ไม่ได้เชื่อมต่อกับ แป้นพิมพ์เสมือน และบล็อกมุมมองทั้งหมดภายใต้ช่องดังกล่าวไม่ให้เชื่อมต่อกับ แป้นพิมพ์เสมือน วิธีนี้มีประโยชน์ในการแสดงกล่องโต้ตอบแอปที่ไม่ได้ใช้ข้อความ เหนือเลเยอร์แป้นพิมพ์FLAG_NOT_FOCUSABLE
และFLAG_ALT_FOCUSABLE_IM
: อยู่ด้านหลังเลเยอร์แป้นพิมพ์แบบย่อ แต่ไม่สามารถรับข้อความได้FLAG_NOT_FOCUSABLE
และFLAG_NOT_TOUCH_MODAL
: ที่ด้านบนของแป้นพิมพ์เสมือนและอนุญาตให้กิจกรรมการสัมผัสสามารถ "ผ่าน" หน้าต่างลงบนแป้นพิมพ์เสมือน
สร้างกล่องโต้ตอบ
ใช้FLAG_ALT_FOCUSABLE_IM
ธงหน้าต่างกล่องโต้ตอบเพื่อให้กล่องโต้ตอบอยู่ที่ด้านบนของแป้นพิมพ์เสมือน และ
ป้องกันไม่ให้แป้นพิมพ์เข้าถึงโฟกัส:
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();
สร้างมุมมองโฆษณาซ้อนทับ
สร้างมุมมองโฆษณาซ้อนทับที่ระบุ TYPE_APPLICATION_OVERLAY
ประเภทหน้าต่างและ FLAG_ALT_FOCUSABLE_IM
ธงหน้าต่างตามกิจกรรมเป้าหมายของแป้นพิมพ์เสมือน
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);
แสดงกล่องโต้ตอบหรือมุมมองใต้แป้นพิมพ์เสมือน
แอปของคุณอาจต้องสร้างกล่องโต้ตอบหรือหน้าต่างที่มี พร็อพเพอร์ตี้ต่อไปนี้
- ปรากฏใต้แป้นพิมพ์เสมือนที่ขอโดยกิจกรรมของเครื่องมือแก้ไข เพื่อไม่ให้ได้รับผลกระทบจากการป้อนข้อความ
- รับรู้การเปลี่ยนแปลงของขนาดชิ้นส่วนของแป้นพิมพ์เสมือนเป็น ปรับเลย์เอาต์ของกล่องโต้ตอบหรือหน้าต่าง
ในกรณีนี้ แอปของคุณมีหลายตัวเลือก ส่วนต่อไปนี้ อธิบายตัวเลือกเหล่านี้
สร้างกล่องโต้ตอบ
สร้างกล่องโต้ตอบโดยการตั้งค่าทั้งFLAG_NOT_FOCUSABLE
ธงหน้าต่างและFLAG_ALT_FOCUSABLE_IM
ธงหน้าต่าง:
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();
สร้างมุมมองโฆษณาซ้อนทับ
สร้างมุมมองซ้อนทับโดยตั้งค่าทั้งFLAG_NOT_FOCUSABLE
ธงหน้าต่างและFLAG_ALT_FOCUSABLE_IM
ธงหน้าต่าง:
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);