จัดการระดับการเข้าถึงวิธีการป้อนข้อมูล

เมื่อโฟกัสอินพุตย้ายเข้าหรือออกจากฟิลด์ข้อความที่แก้ไขได้ 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);