Menangani visibilitas metode input

Saat fokus input masuk atau keluar dari kolom teks yang dapat diedit, Android akan menampilkan atau menyembunyikan input —seperti keyboard di layar—sebagai yang sesuai. Sistem juga menentukan bagaimana UI dan kolom teks muncul di atas metode input. Misalnya, ketika ruang vertikal di layar adalah dibatasi, kolom teks mungkin mengisi semua ruang di atas metode input.

Di sebagian besar aplikasi, perilaku default inilah yang diperlukan. Dalam beberapa kasus, meskipun, Anda mungkin ingin lebih banyak kontrol atas visibilitas metode {i>input<i} dan bagaimana pengaruhnya terhadap tata letak. Pelajaran ini menjelaskan cara mengontrol dan merespons visibilitas metode input.

Tampilkan keyboard virtual saat aktivitas dimulai

Meskipun Android memberikan fokus ke bidang teks pertama dalam tata letak Anda saat aktivitas dimulai, namun keyboard tidak ditampilkan. Perilaku ini sesuai karena memasukkan teks mungkin bukan tugas utama dalam aktivitas. Namun, jika memasukkan teks memang tugas utama, seperti di layar {i>login<i}, maka Anda mungkin ingin {i>soft keyboard <i}muncul secara {i>default<i}.

Untuk menampilkan metode input saat aktivitas dimulai, tambahkan metode atribut android:windowSoftInputMode ke atribut <activity> dengan nilai "stateVisible". Contoh:

<application ... >
    <activity
        android:windowSoftInputMode="stateVisible" ... >
        ...
    </activity>
   ...
</application>

Menentukan cara UI Anda merespons

Saat keyboard virtual muncul di layar, akan mengurangi jumlah ruang yang tersedia untuk UI aplikasi Anda. Sistem memutuskan cara menyesuaikan dari UI Anda, tetapi mungkin ada yang salah. Untuk memastikan perilaku terbaik untuk aplikasi Anda, tetapkan bagaimana sistem akan menampilkan UI Anda di sisa ruang penyimpanan.

Untuk menyatakan perlakuan pilihan Anda dalam suatu aktivitas, gunakan Atribut android:windowSoftInputMode dalam elemen <activity> manifes Anda dengan salah satu opsi "sesuaikan" masing-masing.

Misalnya, untuk memastikan sistem mengubah ukuran tata letak Anda ke ukuran yang tersedia ruang—yang membuat semua konten tata letak Anda dapat diakses, bahkan jika memerlukan scroll—gunakan "adjustResize":

<application ... >
   <activity
       android:windowSoftInputMode="adjustResize" ... >
       ...
   </activity>
   ...
</application>

Anda dapat menggabungkan spesifikasi penyesuaian dengan keyboard virtual awal visibilitas dari bagian sebelumnya:

<activity
    android:windowSoftInputMode="stateVisible|adjustResize" ... >
    ...
</activity>

Menentukan "adjustResize" penting jika UI Anda menyertakan kontrol yang mungkin perlu mengakses segera setelah atau saat melakukan {i>input<i} teks. Sebagai misalnya, jika Anda menggunakan tata letak relatif untuk menempatkan bilah tombol di bagian bawah layar, menggunakan "adjustResize" akan mengubah ukuran tata letak sehingga panel tombol muncul di atas keyboard virtual.

Tampilkan keyboard virtual on demand

Jika ada metode dalam siklus proses aktivitas tempat Anda ingin memastikan metode input terlihat, Anda dapat menggunakan InputMethodManager untuk menunjukkannya.

Misalnya, metode berikut mengambil View tempat pengguna diharapkan ketik sesuatu, panggilan requestFocus() untuk memberikannya fokus, lalu memanggil showSoftInput() untuk membuka metode input:

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);
   }
}

Menampilkan keyboard virtual dengan andal

Ada situasi tertentu, seperti ketika suatu aktivitas dimulai, ketika menggunakan InputMethodManager.showSoftInput() untuk menampilkan keyboard virtual dapat mengakibatkan {i>keyboard<i} perangkat lunak tidak terlihat oleh pengguna.

Visibilitas keyboard virtual saat menggunakan showSoftInput() bergantung pada pada kondisi berikut:

  • Tampilan harus sudah terhubung ke keyboard virtual. (Pada gilirannya, mengharuskan jendela difokuskan dan editor untuk meminta fokus tampilan. View.requestFocus())

  • Visibilitas juga dapat dipengaruhi oleh android:windowSoftInputMode dan flag yang digunakan oleh showSoftInput().

Dalam kasus penggunaan tertentu, seperti saat suatu aktivitas dimulai, beberapa kondisi yang disyaratkan tidak terpenuhi. Sistem tidak menganggap tampilan itu sebagai terhubung ke keyboard virtual, mengabaikan panggilan showSoftInput(), dan {i>soft keyboard<i} tidak terlihat oleh pengguna.

Untuk memastikan keyboard virtual dapat ditampilkan dengan andal, Anda dapat menggunakan alternatif:

  • (Direkomendasikan) Gunakan WindowInsetsControllerCompat. Objek ini menampilkan keyboard virtual selama Activity.onCreate() seperti yang ditunjukkan di cuplikan kode berikut. Panggilan dijamin akan dijadwalkan setelah periode tersebut berfokus.

Kotlin

editText.requestFocus()
WindowCompat.getInsetsController(window, editText)!!.show(WindowInsetsCompat.Type.ime())

Java

editText.requestFocus();
WindowCompat.getInsetsController(getWindow(), editText).show(WindowInsetsCompat.Type.ime());

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);
      });
    }
  }
}

Menangani tanda visibilitas runtime dengan hati-hati

Saat mengalihkan visibilitas keyboard virtual saat runtime, berhati-hatilah agar tidak meneruskan nilai flag ke dalam metode ini. Misalnya, jika aplikasi mengharapkan keyboard virtual muncul saat menelepon View.getWindowInsetsController().show(ime()) di Activity.onCreate() selama pengembang aplikasi harus berhati-hati agar tidak mengatur Tanda SOFT_INPUT_STATE_HIDDEN atau SOFT_INPUT_STATE_ALWAYS_HIDDEN selama peluncuran awal jika keyboard virtual tersembunyi secara tidak terduga.

Sistem biasanya menyembunyikan keyboard virtual secara otomatis

Biasanya, sistem akan menangani penyembunyian keyboard virtual. Ini dapat berupa salah satu kasus berikut:

  • Pengguna menyelesaikan tugas di kolom teks.
  • Pengguna menekan tombol kembali atau gestur geser dengan navigasi kembali.
  • Pengguna membuka aplikasi lain, dan aplikasi lain itu telah menetapkan Tanda SOFT_INPUT_STATE_HIDDEN atau SOFT_INPUT_STATE_ALWAYS_HIDDEN saat tampilan mendapatkan fokus.

Sembunyikan keyboard virtual secara manual berdasarkan perilaku sistem sebelumnya

Dalam beberapa situasi, aplikasi Anda harus menyembunyikan keyboard virtual secara manual— misalnya, saat {i>field<i} teks kehilangan fokus di View.OnFocusChangeListener.onFocusChange Gunakan teknik ini dengan bijak ; menutup {i>soft keyboard<i} secara tiba-tiba mengganggu pengalaman pengguna.

Jika aplikasi Anda menyembunyikan keyboard virtual secara manual, Anda perlu mengetahui apakah keyboard virtual ditampilkan secara eksplisit atau implisit:

  • Keyboard virtual dianggap telah secara eksplisit ditampilkan setelah panggilan ke showSoftInput().

  • Sebaliknya, {i>soft keyboard<i} dianggap telah ditunjukkan secara implisit dalam salah satu kondisi berikut:

Biasanya, hideSoftInputFromWindow() menyembunyikan keyboard virtual, terlepas dari cara permintaan tersebut, tetapi dengan HIDE_IMPLICIT_ONLY itu bisa dibatasi hanya untuk menutup {i>keyboard<i} yang diminta secara implisit.

Menampilkan tampilan dialog atau overlay di atas keyboard virtual

Dalam beberapa situasi, aktivitas editor mungkin perlu membuat jendela dialog atau overlay di atas keyboard virtual.

Aplikasi Anda memiliki beberapa opsi, yang dijelaskan di bagian berikut.

Singkatnya, pastikan untuk menangani tanda jendela keyboard virtual dengan benar menargetkan jendela sedemikian rupa sehingga memenuhi harapan berikut mengenai pengurutan vertikal (lapisan z):

  • Tidak ada flag (kasus normal): Di belakang lapisan keyboard virtual, dan dapat menerima teks.
  • FLAG_NOT_FOCUSABLE : Di atas lapisan keyboard virtual, tetapi tidak dapat menerima teks.
  • FLAG_ALT_FOCUSABLE_IM : Di atas lapisan keyboard virtual, dapat difokuskan tetapi tidak terhubung ke keyboard virtual. Juga memblokir semua tampilan di bawahnya agar tidak terhubung ke keyboard virtual. Hal ini berguna untuk menampilkan dialog aplikasi yang tidak menggunakan teks input di atas lapisan keyboard virtual.
  • FLAG_NOT_FOCUSABLE dan FLAG_ALT_FOCUSABLE_IM : Di belakang lapisan keyboard virtual, tetapi tidak dapat menerima teks.
  • FLAG_NOT_FOCUSABLE dan FLAG_NOT_TOUCH_MODAL : Di atas keyboard virtual, dan memungkinkan peristiwa sentuh untuk "melalui" jendela ke {i>soft keyboard<i}.

Membuat dialog

Menggunakan FLAG_ALT_FOCUSABLE_IM flag jendela dialog untuk menjaga dialog tetap di atas keyboard virtual, dan mencegah keyboard virtual mendapatkan fokus:

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();

Membuat tampilan overlay

Buat tampilan overlay yang menetapkan TYPE_APPLICATION_OVERLAY jenis jendela dan FLAG_ALT_FOCUSABLE_IM penanda jendela oleh aktivitas bertarget keyboard virtual.

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);

Menampilkan dialog atau tampilan di bawah keyboard virtual

Aplikasi Anda mungkin perlu membuat dialog atau jendela yang memiliki properti berikut:

  • Muncul di bawah keyboard virtual yang diminta oleh aktivitas editor sedemikian rupa, sehingga tidak terpengaruh oleh input teks.
  • Tetap mengetahui perubahan ukuran inset keyboard virtual menjadi menyesuaikan dialog atau tata letak jendela.

Dalam hal ini, aplikasi Anda memiliki beberapa opsi. Bagian berikut menjelaskan opsi-opsi ini.

Membuat dialog

Membuat dialog dengan menyetel FLAG_NOT_FOCUSABLE flag jendela dan FLAG_ALT_FOCUSABLE_IM flag jendela:

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();

Membuat tampilan overlay

Buat tampilan overlay dengan menyetel FLAG_NOT_FOCUSABLE flag jendela dan FLAG_ALT_FOCUSABLE_IM flag jendela:

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);