نظرة عامة على أحداث الإدخال

تجربة طريقة ComposeAllowed
Jetpack Compose هي مجموعة أدوات واجهة المستخدم التي ننصح بها لنظام التشغيل Android. تعرَّف على كيفية استخدام اللمس والإدخال في ميزة "إنشاء".

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

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

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

أدوات معالجة الأحداث

أداة معالجة الأحداث هي واجهة في الفئة View تحتوي على عنصر . ويستدعي إطار عمل Android هذه الطرق عند استخدام طريقة العرض التي لدى المستمع تسجيلها من خلال تفاعل المستخدم مع العنصر في واجهة المستخدم.

ويتم تضمين طرق معاودة الاتصال التالية في واجهات أداة معالجة الأحداث:

onClick()
من View.OnClickListener. ويسمى ذلك عندما يلمس المستخدم العنصر (عندما يكون في وضع اللمس) أو يركز على العنصر باستخدام مفاتيح التنقل أو كرة التتبع يضغط على "Enter" المناسب أو يضغط لأسفل على كرة التتبع.
onLongClick()
من View.OnLongClickListener. يُعرف هذا الإجراء عندما يلمس المستخدم العنصر مع الاستمرار (عندما يكون في وضع اللمس) أو يركز على العنصر باستخدام مفاتيح التنقل أو كرة التتبع يضغط مع الاستمرار على "Enter" المناسب مفتاح أو الضغط مع الاستمرار على كرة التتبع (لمدة ثانية واحدة).
onFocusChange()
من View.OnFocusChangeListener. ويسمى ذلك عندما ينتقل المستخدم إلى العنصر أو بعيدًا عنه، باستخدام مفاتيح التنقل أو كرة التتبع.
onKey()
من View.OnKeyListener. ويسمى ذلك عندما يركز المستخدم على العنصر ويضغط على مفتاح الجهاز أو يطلقه على الجهاز.
onTouch()
من View.OnTouchListener. يتم استدعاء ذلك عندما ينفِّذ المستخدم إجراءً مؤهلاً كحدث لمس، بما في ذلك الصحافة أو الإصدار أو أي إيماءة حركة على الشاشة (ضمن حدود العنصر).
onCreateContextMenu()
من View.OnCreateContextMenuListener. ويسمى ذلك عندما يتم إنشاء "قائمة سياق" (نتيجة لـ "نقرة طويلة" مستمرة). الاطّلاع على المناقشة على قوائم السياقات في القوائم. دليل المطوِّرين.

هذه الطرق هي السكان الوحيدون في واجهتها الخاصة. لتحديد إحدى هذه الطرق ومعالجة الأحداث، يمكنك تنفيذ الواجهة المتداخلة في نشاطك أو تحديدها كفئة مجهولة المصدر. بعد ذلك، مرّر مثيلاً لعملية التنفيذ إلى طريقة View.set...Listener() المعنية. (على سبيل المثال، الاتصال setOnClickListener() وتمريره بعد تنفيذ OnClickListener).

يوضح المثال أدناه كيفية تسجيل مستمع عند النقر فوق أحد الأزرار.

Kotlin

protected void onCreate(savedValues: Bundle) {
    ...
    val button: Button = findViewById(R.id.corky)
    // Register the onClick listener with the implementation above
    button.setOnClickListener { view ->
        // do something when the button is clicked
    }
    ...
}

Java

// Create an anonymous implementation of OnClickListener
private OnClickListener corkyListener = new OnClickListener() {
    public void onClick(View v) {
      // do something when the button is clicked
    }
};

protected void onCreate(Bundle savedValues) {
    ...
    // Capture our button from layout
    Button button = (Button)findViewById(R.id.corky);
    // Register the onClick listener with the implementation above
    button.setOnClickListener(corkyListener);
    ...
}

قد يكون من الملائم أيضًا تنفيذ OnClickListener كجزء من نشاطك. سيؤدي هذا الإجراء إلى تجنُّب تحميل الفئة الإضافية وتخصيص العنصر. مثلاً:

Kotlin

class ExampleActivity : Activity(), OnClickListener {
  
    protected fun onCreate(savedValues: Bundle) {
        val button: Button = findViewById(R.id.corky)
        button.setOnClickListener(this)
    }

    // Implement the OnClickListener callback
    fun onClick(v: View) {
        // do something when the button is clicked
    }
}

Java

public class ExampleActivity extends Activity implements OnClickListener {
    protected void onCreate(Bundle savedValues) {
        ...
        Button button = (Button)findViewById(R.id.corky);
        button.setOnClickListener(this);
    }

    // Implement the OnClickListener callback
    public void onClick(View v) {
      // do something when the button is clicked
    }
    ...
}

لاحِظ أنّ دالة الاستدعاء onClick() في المثال أعلاه تتضمّن لا توجد قيمة معروضة، ولكن يجب أن تعرض بعض طرق معالجة الأحداث الأخرى قيمة منطقية. السبب حسب الحدث. وبالنسبة إلى الأنشطة القليلة التي تفعل ذلك، إليك السبب:

  • onLongClick() - يؤدي ذلك إلى عرض قيمة منطقية للإشارة إلى ما إذا كنت قد استهلاكت الحدث ويجب عدم مواصلة تشغيله مرة أخرى. ويعني ذلك عرض القيمة صحيح للإشارة إلى أنّك تعاملت مع الحدث وأنّه يجب أن يتوقف عند هذا الحد. قم بإرجاع false إذا لم تكن قد تعاملت معه و/أو ينبغي أن يستمر الحدث إلى أيٍ آخر المستمعين عند النقر.
  • onKey() - يؤدي ذلك إلى عرض قيمة منطقية للإشارة إلى ما إذا كنت قد استهلاكت الحدث ويجب عدم مواصلة تشغيله مرة أخرى. ويعني ذلك عرض القيمة صحيح للإشارة إلى أنّك تعاملت مع الحدث وأنّه يجب أن يتوقف عند هذا الحد. قم بإرجاع false إذا لم تكن قد تعاملت معه و/أو ينبغي أن يستمر الحدث إلى أيٍ آخر المستمعين الجدد.
  • onTouch() - يعرض ذلك قيمة منطقية للإشارة إلى ما إذا كان المستمع يستنفد هذا الحدث. الشيء المهم هو أن يمكن أن يتضمّن هذا الحدث إجراءات متعدّدة تتبع بعضها بعضًا. لذلك، في حال عرض القيمة false عند عرض حدث إجراء سلبي، ويشير إلى أنك لم تستخدم الحدث غير مهتم بالإجراءات اللاحقة من هذا الحدث. وبالتالي، لن يُطلب منك اتخاذ أي إجراءات أخرى. داخل الحدث، مثل إيماءة الإصبع أو حدث الإجراء النهائي.

تذكَّر أنّه يتم دائمًا تسليم الأحداث الرئيسية للأجهزة إلى العرض محلّ التركيز حاليًا. يتم إرسالها بدءًا من الأعلى العرض الهرمي ثم أسفلها حتى تصل إلى الوجهة المناسبة. إذا كان ملفك الشخصي (أو عنصر فرعي من ملفك الشخصي) محلّ التركيز حاليًا، يمكنك حينها الاطّلاع على مسار الحدث من خلال طريقة dispatchKeyEvent(). كخيار بديل لتسجيل الأحداث الرئيسية من خلال ملفك الشخصي، يمكنك أيضًا جميع الأحداث ضمن نشاطك مع "onKeyDown()" وonKeyUp().

كذلك، عند التفكير في إدخال النص لتطبيقك، تذكر أن العديد من الأجهزة لا تحتوي إلا على إدخالات برامج الطرق. وليس من الضروري أن تكون هذه الطرق مستندة إلى مفتاح، والبعض الآخر قد يستخدم الإدخال الصوتي والكتابة بخط اليد وما إلى ذلك. حتى إذا أسلوب الإدخال إذا كان واجهة تشبه لوحة المفاتيح، فلن يؤدي بشكل عام إلى تشغيل مجموعة أحداث onKeyDown() لا ينبغي عليك أبدًا إنشاء واجهة مستخدم تتطلب ضغطات مفاتيح معينة للتحكم فيها، إلا إذا كنت ترغب في أن يقتصر تطبيقك على الأجهزة باستخدام لوحة مفاتيح خارجية. وعلى وجه الخصوص، لا تعتمد على هذه الطرق للتحقق من صحة الإدخال عندما يضغط المستخدم على return key; بدلاً من ذلك، استخدِم إجراءات مثل IME_ACTION_DONE للإشارة إلى الإدخال بالشكل الذي يتوقعه تطبيقك أن يتفاعل معه، لذلك قد يغيّر واجهة المستخدم الخاصة به بطريقة مجدية. تجنب الافتراضات حول كيفية عمل أسلوب إدخال البرنامج والوثوق به فقط لتقديم نص تم تنسيقه بالفعل إلى تطبيقك.

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

معالِجات الأحداث

إذا كنت تنشئ مكوِّنًا مخصّصًا من "العرض"، ستتمكّن من تحديد طرق استدعاء متعددة. استخدامها كمعالجات تلقائية للأحداث في المستند المتعلق بـ تخصيص في "عرض المكونات"، ستتعرف على بعض عمليات الاستدعاء الشائعة المستخدمة في معالجة الأحداث، بما في ذلك:

هناك بعض الطرق الأخرى التي ينبغي أن تكون على دراية بها، والتي لا تمثل جزءًا من فئة العرض، لكنّها قد تؤثّر مباشرةً في طريقة التعامل مع الأحداث لذلك، عند إدارة الأحداث الأكثر تعقيدًا داخل التخطيط، ضع في اعتبارك هذه الطرق الأخرى:

وضع اللمس

عندما يتنقل مستخدم في واجهة المستخدم باستخدام مفاتيح الاتجاهات أو كرة التتبع، ضرورية لمنح التركيز على العناصر القابلة للتنفيذ (مثل الأزرار) حتى يتمكن المستخدم من رؤية ما الذي يقبل المدخلات. ولكن إذا كان الجهاز مزوّدًا بإمكانيات اللمس، وتمكّن المستخدم من التفاعل مع الواجهة من خلال لمسها، فلن يكون ضروريًا أو تمييز العناصر، أو التركيز على عرض معين. وبالتالي، هناك وضع للتفاعل باسم "وضع اللمس".

بالنسبة للأجهزة التي تعمل باللمس، فبمجرد لمس المستخدم للشاشة، سيتم سيتم الدخول في وضع اللمس. من الآن فصاعدًا، ستظهر فقط المشاهدات التي قيمة isFocusableInTouchMode() هي القيمة "صحيح" التي يمكن التركيز عليها، مثل التطبيقات المصغّرة لتعديل النصوص. لن يتم التركيز على طرق العرض الأخرى التي يمكن لمسها، مثل الأزرار، عند لمسها؛ سوف أجهزة المستمعين عند النقر عند الضغط عليها.

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

يتم الاحتفاظ بحالة وضع اللمس في جميع أنحاء النظام (جميع النوافذ والأنشطة). للاستعلام عن الحالة الحالية، يمكنك استدعاء يمكنك isInTouchMode() لمعرفة ما إذا كان الجهاز في وضع اللمس حاليًا.

التعامل مع التركيز

سيتعامل إطار العمل مع حركة التركيز الروتينية استجابةً لإدخال المستخدم. ويشمل هذا تغيير التركيز حيث تتم إزالة طرق العرض أو إخفاؤها أو تغيير تصبح المشاهدات متاحة. تشير المشاهدات إلى استعداده للتركيز من خلال الطريقة isFocusable(). لتغيير ما إذا كان يمكن أن تستغرق إحدى المشاهدات التركيز، الاتصال بـ setFocusable(). عندما تكون في وضع اللمس، يمكنك الاستعلام عما إذا كان الملف الشخصي يسمح بالتركيز باستخدام isFocusableInTouchMode(). يمكنك تغيير هذا الخيار باستخدام setFocusableInTouchMode().

على الأجهزة التي تعمل بنظام التشغيل Android 9 (المستوى 28 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث، لا تحدِّد الأنشطة التركيز الأوّلي. بدلاً من ذلك، يجب عليك طلب التركيز الأوّلي بشكل صريح، إذا رغبت في ذلك.

تعتمد حركة التركيز على خوارزمية تحدد الجار الأقرب في توجيه معين. في حالات نادرة، قد لا تتطابق الخوارزمية الافتراضية مع والسلوك المقصود لمطور البرامج. في هذه الحالات، يمكنك تقديم عمليات الإلغاء الواضحة مع سمات XML التالية في ملف التنسيق: nextFocusDown وnextFocusLeft وnextFocusRight و nextFocusUp أضف إحدى هذه السمات إلى العرض من الذي التركيز هو المغادرة. تحديد قيمة السمة لتكون رقم تعريف الملف الشخصي إلى التركيز الذي يجب التركيز عليه. مثلاً:

<LinearLayout
    android:orientation="vertical"
    ... >
  <Button android:id="@+id/top"
          android:nextFocusUp="@+id/bottom"
          ... />
  <Button android:id="@+id/bottom"
          android:nextFocusDown="@+id/top"
          ... />
</LinearLayout>

وعادةً، في هذا التخطيط العمودي، لن يؤدي التنقل لأعلى من الزر الأول في أي مكان، ولا التنقل لأسفل من الزر الثاني. الآن بعد أن أصبح الزر العلوي حدد الجزء السفلي على أنه nextFocusUp (والعكس صحيح)، فإن تركيز التنقل الدورة من أعلى إلى أسفل ومن أسفل إلى أعلى.

إذا أردت الإشارة إلى أنّ إحدى طرق العرض يمكن التركيز عليها في واجهة المستخدم (عندما لا يكون ذلك ممكنًا في العادة)، أضِف سمة XML android:focusable إلى العرض في بيان التنسيق. حدِّد القيمة true. يمكنك أيضًا الإفصاح عن طريقة عرض يمكن التركيز عليها أثناء استخدام "وضع اللمس" مع "android:focusableInTouchMode".

لطلب وضع تركيز معيّن في ملف شخصي معيّن، يمكنك الاتصال بالرقم requestFocus().

للاستماع إلى أحداث التركيز (الحصول على إشعار عند تلقي طريقة عرض أو فقدان التركيز)، استخدم onFocusChange(), كما هو موضَّح في قسم مستمعي الأحداث.