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

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