Giriş yöntemi görünürlüğünü işleme

Giriş odağı düzenlenebilir bir metin alanının içine veya dışına taşındığında Android, girişi (ör. dokunmatik klavye) uygun şekilde gösterir veya gizler. Sistem, kullanıcı arayüzünüzün ve metin alanının giriş yönteminin üzerinde nasıl görüneceğine de karar verir. Örneğin, ekrandaki dikey alan kısıtlandığında metin alanı, giriş yönteminin üzerindeki tüm alanı doldurabilir.

Çoğu uygulama için bu varsayılan davranışlar yalnızca gereklidir. Yine de bazı durumlarda, giriş yönteminin görünürlüğü ve düzeni nasıl etkilediği üzerinde daha fazla kontrol sahibi olmak isteyebilirsiniz. Bu derste, giriş yöntemi görünürlüğünün nasıl kontrol edileceği ve yanıtlanacağı açıklanır.

Etkinlik başladığında ekran klavyesini göster

Android, etkinlik başladığında düzeninizdeki ilk metin alanına odaklanma sağlasa da sanal klavyeyi göstermez. Etkinlikteki asıl görev metin girmek olmayabileceğinden bu davranış uygundur. Bununla birlikte, giriş ekranı gibi bir asıl görev metin girmekse muhtemelen sanal klavyenin varsayılan olarak görünmesini istersiniz.

Etkinliğiniz başladığında giriş yöntemini göstermek için android:windowSoftInputMode özelliğini "stateVisible" değerine sahip <activity> öğesine ekleyin. Örneğin:

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

Kullanıcı arayüzünüzün nasıl yanıt vermesi gerektiğini belirtin

Yumuşak klavye ekranda göründüğünde, uygulamanızın kullanıcı arayüzü için kullanılabilen alan miktarını azaltır. Sistem, kullanıcı arayüzünüzün görünür bölümünün nasıl ayarlanacağına karar verir, ancak doğru şekilde çalışmayabilir. Uygulamanız için en iyi davranışı sağlamak amacıyla, kalan alanda sistemin kullanıcı arayüzünüzü nasıl görüntülemesini istediğinizi belirtin.

Bir etkinlikte tercih ettiğiniz işlemi belirtmek için manifest'inizin <activity> öğesinde android:windowSoftInputMode özelliğini "adjust" değerlerinden biriyle kullanın.

Örneğin, sistemin düzeninizi kullanılabilir alana göre yeniden boyutlandırmasını sağlamak ve böylece kaydırma gerektirse bile düzen içeriğinizin tamamını erişilebilir kılmak için "adjustResize" değerini kullanın:

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

Ayarlama spesifikasyonunu, önceki bölümde bulunan ilk yazılım klavyesi görünürlüğü spesifikasyonuyla birleştirebilirsiniz:

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

Kullanıcı arayüzünüzde, kullanıcının metin girişi yaptıktan hemen sonra veya çalışırken erişmesi gereken kontroller varsa "adjustResize" belirtilmesi önemlidir. Örneğin, ekranın alt kısmına bir düğme çubuğu yerleştirmek için göreli bir düzen kullanıyorsanız, "adjustResize" kullanıldığında düzen yeniden boyutlandırılır ve düğme çubuğu elektronik klavyenin üzerinde görünür.

Yumuşak klavyeyi istek üzerine gösterin

Etkinliğinizin yaşam döngüsünde giriş yönteminin görünür olduğundan emin olmak istediğiniz bir yöntem varsa bunu göstermek için InputMethodManager kullanabilirsiniz.

Örneğin, aşağıdaki yöntemde kullanıcının bir şey yazması beklenen bir View kullanılır, odak vermek için requestFocus() ve ardından giriş yöntemini açmak için showSoftInput() çağrılır:

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

Yumuşak klavyeyi güvenilir bir şekilde gösterin

Bir etkinliğin başlaması gibi, sanal klavyeyi görüntülemek için InputMethodManager.showSoftInput() kullanmanın yazılım klavyesinin kullanıcı tarafından görülememesine neden olabileceği belirli durumlar vardır.

showSoftInput() kullanılırken sanal klavyenin görünürlüğü aşağıdaki koşullara bağlıdır:

  • Görünüm yazılım klavyesine bağlı olmalıdır. (Bu durumda, pencerenin odaklanılması ve düzenleyici görünümünün View.requestFocus() ile görünüm odağı isteğinde bulunması gerekir).

  • Görünürlük, android:windowSoftInputMode özelliğinden ve showSoftInput() tarafından kullanılan işaretlerden de etkilenebilir.

Bir etkinliğin başlaması gibi belirli kullanım durumlarında bu gerekli koşullardan bazıları karşılanmaz. Sistem, görünümü yazılım klavyesine bağlı olarak kabul etmez, showSoftInput() çağrısını yoksayar ve yazılım klavyesi kullanıcı tarafından görülemez.

Yazılım klavyesinin güvenilir bir şekilde gösterildiğinden emin olmak için aşağıdaki alternatifleri kullanabilirsiniz:

  • (Önerilen) WindowInsetsControllerCompat simgesini kullanın. Bu nesne, aşağıdaki kod snippet'inde gösterildiği gibi Activity.onCreate() sırasında yazılım klavyesini görüntüler. Görüşmenin, zaman aralığı ayarlandıktan sonra planlanacağı garanti edilir.

Kotlin

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

Java

editText.requestFocus();
WindowCompat.getInsetsController(getWindow(), editText).show(WindowInsetsCompat.Type.ime());
  • Çalıştırılabilir bir dosya yayınlayın. Bu, uygulamanızın showSoftInput() yöntemini çağırmadan önce View.onWindowFocusChanged() ürününden pencere odaklanma etkinliğini alana kadar beklemesini sağlar.

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

Çalışma zamanı görünürlük bayraklarını dikkatli bir şekilde yönetin

Çalışma zamanında elektronik klavye görünürlüğünü değiştirirken, bu yöntemlere belirli işaret değerlerini geçirmemeye dikkat edin. Örneğin, uygulama etkinlik başladığında Activity.onCreate() içinde View.getWindowInsetsController().show(ime()) çağrısı yapıldığında sanal klavyenin gösterilmesini bekliyorsa yazılım klavyesinin beklenmedik bir şekilde gizlenmesi ihtimaline karşı uygulama geliştiricileri, ilk başlatma sırasında SOFT_INPUT_STATE_HIDDEN veya SOFT_INPUT_STATE_ALWAYS_HIDDEN işaretlerini ayarlamamaya dikkat etmelidir.

Sistem genellikle yazılım klavyesini otomatik olarak gizler

Çoğu durumda sistem klavyenin gizlenmesini sağlar. Bu, aşağıdaki durumlardan herhangi biri olabilir:

  • Kullanıcı, metin alanındaki görevi tamamlar.
  • Kullanıcı, geri tuşuna basar veya geri gezinme sırasında kaydırma hareketlerini yapar.
  • Kullanıcı başka bir uygulamaya gider ve görünüm odağı ele aldığında diğer uygulama SOFT_INPUT_STATE_HIDDEN veya SOFT_INPUT_STATE_ALWAYS_HIDDEN işaretlerini ayarlamıştır.

Önceki sistem davranışına göre sanal klavyeyi manuel olarak gizle

Uygulamanızın, bazı durumlarda (örneğin, View.OnFocusChangeListener.onFocusChange'te metin alanının odağı kaybolduğunda) sanal klavyeyi manuel olarak gizlemesi gerekir. Bu tekniği mantıklı bir şekilde kullanın. Bilgisayar klavyesinin kapatılması beklenmedik bir şekilde kullanıcı deneyimini olumsuz etkiler.

Uygulamanız sanal klavyeyi manuel olarak gizliyorsa klavyenin açıkça mı yoksa örtülü olarak mı gösterildiğini bilmeniz gerekir:

  • Yumuşak klavyenin showSoftInput() için yapılan bir çağrıdan sonra açıkça gösterildiği kabul edilir.

  • Buna karşılık, elektronik klavyenin aşağıdaki koşullardan herhangi birinde dolaylı olarak gösterildiği kabul edilir:

    • android:windowSoftInputMode uygulanırken sistemde yazılım klavyesi gösterildi.
    • Uygulamanız, showSoftInput() için SHOW_IMPLICIT testini geçti.

Normalde hideSoftInputFromWindow(), sanal klavyeyi nasıl istendiğine bakılmaksızın gizler ancak HIDE_IMPLICIT_ONLY ile yalnızca dolaylı olarak istenen bir yazılım klavyesini kapatmakla sınırlandırılabilir.

Yumuşak klavyenin üstünde iletişim kutusu veya yer paylaşımlı görünüm göster

Bazı durumlarda, düzenleyici etkinliğinin sanal klavyenin üst kısmında, düzenlenebilir olmayan bir iletişim kutusu veya yer paylaşımlı pencere oluşturması gerekebilir.

Uygulamanızda birkaç seçenek var. Bunlar aşağıdaki bölümlerde açıklanmıştır.

Özetle, pencereyi hedefleyen yazılım klavyesinin pencere işaretlerini, dikey (z katmanı) sıralamayla ilgili aşağıdaki beklentileri karşılayacak şekilde doğru bir şekilde ele aldığınızdan emin olun:

  • İşaret yok (normal büyük/küçük harf): Yumuşak klavye katmanının arkasındadır ve metin alabilir.
  • FLAG_NOT_FOCUSABLE : Yumuşak klavye katmanının üzerindedir, ancak metin alamaz.
  • FLAG_ALT_FOCUSABLE_IM : Yumuşak klavye katmanının üst kısmında odaklanılabilir, ancak ekran klavyesine bağlı değildir. Ayrıca, altındaki tüm görünümlerin klavyeye bağlanmasını da engeller. Bu, elektronik klavye katmanının üzerinde metin girişi kullanmayan bir uygulama iletişim kutusunu göstermek için yararlıdır.
  • FLAG_NOT_FOCUSABLE ve FLAG_ALT_FOCUSABLE_IM : Yumuşak klavye katmanının arkasındadır, ancak metin alamaz.
  • FLAG_NOT_FOCUSABLE ve FLAG_NOT_TOUCH_MODAL : Yumuşak klavyenin üstünde ve dokunma etkinliklerinin pencereden yazılım klavyesine "geçmesine" izin ver.

İletişim kutusu oluştur

İletişim kutusunu yazılım klavyesinin üzerinde tutmak ve yazılım klavyesinin odaklanmasını önlemek için FLAG_ALT_FOCUSABLE_IM iletişim kutusu pencere işaretini kullanın:

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

Yer paylaşımlı görünüm oluşturma

Sanal klavye hedefli etkinliğe göre TYPE_APPLICATION_OVERLAY pencere türünü ve FLAG_ALT_FOCUSABLE_IM pencere işaretini belirten bir yer paylaşımlı görünüm oluşturun.

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

Sanal klavyenin altında iletişim kutusu veya görünüm göster

Uygulamanızın aşağıdaki özelliklere sahip bir iletişim kutusu veya pencere oluşturması gerekebilir:

  • Bir düzenleyici etkinliği tarafından istenen yazılım klavyesinin altında görünür ve metin girişinden etkilenmez.
  • İletişim kutusunun veya pencerenin düzenini ayarlamak için yazılım klavyesinin boyut değişikliklerinden haberdar olur.

Bu durumda, uygulamanızda birkaç seçenek vardır. Aşağıdaki bölümlerde bu seçenekler açıklanmaktadır.

İletişim kutusu oluştur

Hem FLAG_NOT_FOCUSABLE pencere işaretini hem de FLAG_ALT_FOCUSABLE_IM pencere işaretini ayarlayarak bir iletişim kutusu oluşturun:

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

Yer paylaşımlı görünüm oluşturma

Hem FLAG_NOT_FOCUSABLE pencere işaretini hem de FLAG_ALT_FOCUSABLE_IM pencere işaretini ayarlayarak bir bindirme görünümü oluşturun:

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