التعامل مع الإذن بالوصول إلى طريقة الإدخال

عندما ينتقل تركيز الإدخال إلى حقل نصي قابل للتعديل أو خارجه، يعرض Android أو لإخفاء الإدخال — مثل لوحة المفاتيح على الشاشة — باسم مناسبًا. يحدِّد النظام أيضًا كيفية ظهور واجهة المستخدم وحقل النص أعلاه. أسلوب الإدخال. على سبيل المثال، عندما تكون المساحة الرأسية على الشاشة فقد يملأ حقل النص كل المساحة فوق أسلوب الإدخال.

بالنسبة إلى معظم التطبيقات، تكون هذه السلوكيات التلقائية هي كل ما هو مطلوب. في بعض الحالات، قد ترغب في التحكم بشكل أكبر في مستوى رؤية أسلوب الإدخال وكيف يؤثر على التخطيط. يشرح هذا الدرس كيفية التحكم في مستوى رؤية أسلوب الإدخال.

عرض لوحة المفاتيح الافتراضية عند بدء النشاط

وعلى الرغم من أن Android يعطي التركيز على حقل النص الأول في التخطيط لديك عندما بدء النشاط، إلا أن لوحة المفاتيح الافتراضية لا تظهر. هذا السلوك مناسب لأن إدخال نص قد لا يكون المهمة الأساسية في النشاط. ومع ذلك، إذا فإن إدخال نص هو المهمة الأساسية بالفعل، كما هو الحال في شاشة تسجيل الدخول، ثم ربما تريد أن تظهر لوحة المفاتيح الافتراضية بشكل افتراضي.

لإظهار أسلوب الإدخال عند بدء نشاطك، أضِف android:windowSoftInputMode إلى سمة العنصر <activity> بالقيمة "stateVisible" مثلاً:

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

تحديد كيفية استجابة واجهة المستخدم

عند ظهور لوحة المفاتيح الافتراضية على الشاشة، يقلل ذلك من المساحة. متاحة لواجهة المستخدم في تطبيقك. يقرر النظام كيفية ضبط مستوى الرؤية من واجهة المستخدم، ولكنها قد لا تفهمها بشكل صحيح. لضمان أفضل سلوك لتطبيقك، فحدِّد الطريقة التي تريد أن يعرض بها النظام واجهة المستخدم في المساحة المتبقية.

للإشارة إلى علاجك المفضّل في أحد الأنشطة، استخدِم السمة android:windowSoftInputMode في العنصر <activity> في ملف البيان باستخدام أحد خيارات "التعديل" القيم.

على سبيل المثال، لضمان تغيير النظام لتغيير حجم التخطيط إلى الحجم المتاح المساحة - والتي تحافظ على إمكانية الوصول إلى كل محتوى التخطيط، حتى لو الانتقال للأسفل، استخدِم "adjustResize":

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

يمكنك الجمع بين مواصفات الضبط ولوحة المفاتيح الرقمية الأولية. مواصفات مستوى الرؤية من القسم السابق:

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

من المهم تحديد "adjustResize" إذا كانت واجهة المستخدم تتضمّن عناصر تحكّم قد يحتاج المستخدم إلى الوصول فورًا بعد إدخال النص أو أثناء تنفيذه. بالنسبة فإذا كنت تستخدم تخطيطًا نسبيًا لوضع شريط الأزرار أسفل الشاشة، باستخدام "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(). وفقًا للشروط التالية:

في بعض حالات الاستخدام، مثل عند بدء نشاط ما، قد يكون بعض هذه لا يتم استيفاء الشروط المطلوبة. لا يعتبر النظام طريقة العرض متصل بلوحة المفاتيح البرمجية، يتجاهل طلب 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 بل يمكن أن يقتصر على إغلاق لوحة مفاتيح افتراضية مطلوبة ضمنًا.

إظهار مربّع حوار أو طريقة عرض مركّبة أعلى لوحة المفاتيح الافتراضية

في بعض الحالات، قد يحتاج نشاط المحرِّر إلى إنشاء مستند غير قابل للتعديل مربع حوار أو نافذة تراكب فوق لوحة المفاتيح الافتراضية.

يتوفّر في تطبيقك بضعة خيارات توضِّح الأقسام التالية.

باختصار، احرص على التعامل مع علامات النوافذ في لوحة المفاتيح الافتراضية بشكل صحيح استهداف النافذة بحيث تلبّي التوقعات التالية فيما يتعلق بالطلب الرأسي (الطبقة 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 علامة window:

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 علامة window:

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