إتاحة ميزات قلم الشاشة المتقدّمة

يتيح قلم الشاشة للمستخدمين التفاعل مع التطبيقات بسهولة وبدقة دقيقة لتدوين الملاحظات والرسم والعمل مع تطبيقات الإنتاجية والاسترخاء والاستمتاع بالألعاب والتطبيقات الترفيهية.

يوفّر نظاما التشغيل Android وChromeOS مجموعة متنوعة من واجهات برمجة التطبيقات لتوفير تجربة استثنائية لقلم الشاشة في التطبيقات. تقدِّم فئة MotionEvent معلومات عن تفاعل المستخدم مع الشاشة، بما في ذلك الضغط باستخدام قلم الشاشة واتجاهه وإمالة الجهاز والتمرير وراحة يده. تعمل الرسومات ذات وقت الاستجابة السريع ومكتبات توقُّع الحركة على تحسين العرض على الشاشة بقلم الشاشة لتوفير تجربة عادية تشبه القلم والورقة.

MotionEvent

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

بيانات الأحداث

للوصول إلى بيانات MotionEvent في التطبيقات المستندة إلى طريقة العرض، يمكنك إعداد onTouchListener:

Kotlin

val onTouchListener = View.OnTouchListener { view, event ->
  // Process motion event.
}

Java

View.OnTouchListener listener = (view, event) -> {
  // Process motion event.
};

يتلقّى المستمع MotionEvent عناصر من النظام، ليتمكن تطبيقك من معالجتها.

يوفّر الكائن MotionEvent بيانات ذات صلة بالجوانب التالية من حدث واجهة المستخدم:

  • الإجراءات: التفاعل المادي مع الجهاز - لمس الشاشة، وتحريك مؤشر فوق سطح الشاشة، وتمرير مؤشر فوق سطح الشاشة
  • المؤشرات: معرّفات العناصر التي تتفاعل مع الشاشة، مثل الإصبع وقلم الشاشة والماوس
  • المحور: نوع البيانات — الإحداثيات س وص، والضغط، والإمالة، والاتجاه، والتمرير (المسافة)

المهام

لتنفيذ دعم قلم الشاشة، يجب أن تفهم الإجراء الذي يقوم به المستخدم.

تقدّم MotionEvent مجموعة متنوعة من ثوابت ACTION التي تحدد أحداث الحركة. تشمل أهم الإجراءات لقلم الشاشة ما يلي:

الإجراء الوصف
ACTION_DOWN
ACTION_POINTER_DOWN
اتصل المؤشر بالشاشة.
ACTION_MOVE يتحرك المؤشر على الشاشة.
ACTION_UP
ACTION_POINTER_UP
لم يعُد المؤشر على اتصال بالشاشة.
إلغاء الإجراء متى يجب إلغاء مجموعة الحركة السابقة أو الحالية؟

يمكن لتطبيقك تنفيذ مهام مثل بدء رسم ضغطة جديد عند حدوث ACTION_DOWN، ورسم الحد الخارجي باستخدام ACTION_MOVE,، وإنهاء الحد عند تشغيل ACTION_UP.

تُعرف مجموعة إجراءات MotionEvent من ACTION_DOWN إلى ACTION_UP لمؤشر معيّن باسم مجموعة الحركة.

مؤشرات

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

تتراوح فهارس المؤشرات من صفر إلى عدد المؤشرات التي يعرضها MotionEvent#pointerCount() ناقص 1.

يمكن الوصول إلى قيم المحور للمؤشرات باستخدام الطريقة getAxisValue(axis, pointerIndex). عند حذف فهرس المؤشر، يعرض النظام قيمة أول مؤشر، وهي صفر (0).

تحتوي كائنات MotionEvent على معلومات عن نوع المؤشر المستخدم. يمكنك الحصول على نوع المؤشر من خلال التكرار من خلال فهارس المؤشر واستدعاء الطريقة getToolType(pointerIndex).

لمعرفة المزيد من المعلومات عن المؤشرات، يمكنك الاطّلاع على التعامل مع إيماءات اللمس المتعدد.

إدخالات قلم الشاشة

يمكنك الفلترة لعرض إدخالات قلم الشاشة باستخدام TOOL_TYPE_STYLUS:

Kotlin

val isStylus = TOOL_TYPE_STYLUS == event.getToolType(pointerIndex)

Java

boolean isStylus = TOOL_TYPE_STYLUS == event.getToolType(pointerIndex);

يمكن لقلم الشاشة أيضًا الإبلاغ عن استخدامه كممحاة مع TOOL_TYPE_ERASER:

Kotlin

val isEraser = TOOL_TYPE_ERASER == event.getToolType(pointerIndex)

Java

boolean isEraser = TOOL_TYPE_ERASER == event.getToolType(pointerIndex);

بيانات محور قلم الشاشة

توفّر السمتان ACTION_DOWN وACTION_MOVE بيانات للمحور حول قلم الشاشة، أي إحداثي س وص، والضغط والاتجاه والإمالة والتمرير.

لتفعيل الوصول إلى هذه البيانات، توفّر واجهة برمجة التطبيقات MotionEvent واجهة برمجة التطبيقات getAxisValue(int)، حيث تكون المعلَمة أي من معرّفات المحاور التالية:

Axis القيمة المعروضة: getAxisValue()
AXIS_X الإحداثي السيني (X) لحدث حركة.
AXIS_Y الإحداثي الصادي لحدث حركة.
AXIS_PRESSURE الضغط بإصبع أو قلم أو مؤشر آخر على الشاشة التي تعمل باللمس أو لوحة اللمس بالنسبة إلى الماوس أو كرة التعقب، 1 إذا تم الضغط على الزر الأساسي، أو 0.
AXIS_ORIENTATION بالنسبة إلى الشاشة التي تعمل باللمس أو لوحة اللمس، يشير هذا إلى اتجاه الإصبع أو قلم الشاشة أو أي مؤشر آخر بالنسبة إلى المستوى الرأسي للجهاز.
AXIS_TILT زاوية إمالة قلم الشاشة بوحدات الراديان.
AXIS_DISTANCE المسافة بين قلم الشاشة والشاشة

على سبيل المثال، تعرض MotionEvent.getAxisValue(AXIS_X) الإحداثي x للمؤشر الأول.

راجِع أيضًا التعامل مع إيماءات اللمس المتعدد.

الموضع

يمكنك استرداد إحداثيات س وص للمؤشر باستخدام الاستدعاءات التالية:

قلم الشاشة يرسم على الشاشة مع ربط الإحداثي س وص.
الشكل 1. إحداثيات شاشتَي "س" و"ص" لمؤشر قلم الشاشة

الضغط

يمكنك استرداد ضغط المؤشر باستخدام الطلبات التالية:

getAxisValue(AXIS_PRESSURE) أو getPressure() للمؤشر الأول.

قيمة الضغط لشاشات اللمس أو لوحات اللمس هي قيمة بين 0 (بدون ضغط) و1، ولكن يمكن عرض قيم أعلى بناءً على معايرة الشاشة.

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

الاتجاه

ويشير الاتجاه إلى الاتجاه الذي يشير إليه قلم الشاشة.

يمكن استرداد اتجاه المؤشر باستخدام getAxisValue(AXIS_ORIENTATION) أو getOrientation() (للمؤشر الأول).

بالنسبة لقلم الشاشة، يتم عرض الاتجاه كقيمة وحدة راديان تتراوح بين 0 وباي (PAN) في اتجاه عقارب الساعة أو من 0 إلى -pi عكس اتجاه عقارب الساعة.

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

الشكل 3. قلم شاشة يشير إلى اليسار بحوالي .57 راديان ناقص.

إمالة

تقيس ميزة "الإمالة" ميل قلم الشاشة بالنسبة إلى الشاشة.

تؤدي الإمالة إلى عرض الزاوية الموجبة لقلم الشاشة بوحدات الراديان، حيث يكون الصفر عموديًا على الشاشة وباي/2 يكون مسطّحًا على السطح.

يمكن استرداد زاوية الإمالة باستخدام "getAxisValue(AXIS_TILT)" (بدون اختصار للمؤشر الأول).

يمكن استخدام ميزة الإمالة لإعادة إنتاج أقرب أدوات ممكنة من الحياة الواقعية، مثل محاكاة التظليل باستخدام قلم رصاص مائل.

قلم الشاشة مائل حوالي 40 درجة عن سطح الشاشة.
الشكل 4. إمالة قلم الشاشة إلى حوالي 0 .785 راديان، أو 45 درجة من الوضع العمودي.

المرور فوق

يمكن تحديد مسافة قلم الشاشة من الشاشة باستخدام getAxisValue(AXIS_DISTANCE). تُرجع الطريقة قيمة من 0.0، عند التلامس مع الشاشة، إلى قيم أعلى عندما يبتعد قلم الشاشة عن الشاشة. تعتمد مسافة التمرير بين الشاشة وسند (النقطة) لقلم الشاشة على الشركة المصنّعة لكل من الشاشة وقلم الشاشة. وبما أنّ عمليات التنفيذ قد تختلف، لا تعتمد على قيم دقيقة للحصول على الوظائف الأساسية للتطبيق.

يمكن استخدام التمرير بقلم الشاشة لمعاينة حجم الفرشاة أو الإشارة إلى اختيار أحد الأزرار.

الشكل 5. قلم شاشة يمرر فوق شاشة يتفاعل التطبيق على الرغم من أنّ قلم الشاشة لا يلامس سطح الشاشة.

ملاحظة: توفّر أداة Compose مجموعة من عناصر التعديل لتغيير حالة عناصر واجهة المستخدم:

  • hoverable: يمكنك ضبط المكوِّن بحيث يمكن التمرير فوقه باستخدام أحداث الدخول والخروج من المؤشر.
  • indication: رسم تأثيرات مرئية لهذا المكوِّن عند حدوث تفاعلات

رفض راحة اليد والتنقّل والإدخالات غير المرغوب فيها

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

ونتيجةً لذلك، يجب الاحتفاظ بسجلّ إدخالات المستخدم حتى يمكن إزالة اللمسات غير المرغوب فيها من الشاشة وإعادة عرض البيانات المشروعة التي أدخلها المستخدم.

ACTION_CANCEL وFLAG_CANCELED

تم تصميم الترميزَين ACTION_CANCEL وFLAG_CANCELED لإعلامك بأنّه يجب إلغاء مجموعة MotionEvent السابقة من آخر ACTION_DOWN، ما يتيح لك مثلاً التراجع عن آخر ضغطة في تطبيق رسم لمؤشر محدّد.

إلغاء الإجراء

تمت إضافتها في Android 1.0 (مستوى واجهة برمجة التطبيقات 1)

تشير السمة ACTION_CANCEL إلى أنه يجب إلغاء المجموعة السابقة من أحداث الحركة.

يتم تشغيل ACTION_CANCEL عند رصد أي مما يلي:

  • إيماءات التنقل
  • رفض راحة اليد

عند تفعيل ACTION_CANCEL، عليك تحديد المؤشر النشط باستخدام getPointerId(getActionIndex()). بعد ذلك، قم بإزالة الحد الخارجي الذي تم إنشاؤه باستخدام هذا المؤشر من سجل الإدخال، ثم أعد عرض المشهد.

FLAG_CANCELED

تمت إضافتها في Android 13 (المستوى 33 من واجهة برمجة التطبيقات)

يشير الرمز FLAG_CANCELED إلى أنّ المؤشر الصاعد كان لمسة غير مقصودة من المستخدم. يتم ضبط العلم عادةً عندما يلمس المستخدم الشاشة عن طريق الخطأ، مثلاً عن طريق الإمساك بالجهاز أو وضع راحة يده على الشاشة.

يمكنك الوصول إلى قيمة العلامة على النحو التالي:

Kotlin

val cancel = (event.flags and FLAG_CANCELED) == FLAG_CANCELED

Java

boolean cancel = (event.getFlags() & FLAG_CANCELED) == FLAG_CANCELED;

في حال ضبط العلامة، عليك التراجع عن آخر مجموعة MotionEvent من آخر ACTION_DOWN في هذا المؤشر.

مثل ACTION_CANCEL، يمكن العثور على المؤشر باستخدام getPointerId(actionIndex).

الشكل 6. يتم إنشاء مجموعة واحدة من MotionEvent من خلال سُمك قلم الشاشة ولمس راحة اليد. تم إلغاء ميزة "لمس راحة اليد" وإعادة عرض الشاشة.

إيماءات ملء الشاشة، والحافة إلى الحافة، وإيماءات التنقل

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

الشكل 7. إيماءة التمرير السريع لنقل التطبيق إلى الخلفية

لمنع الإيماءات من إجراء لمسات غير مرغوب فيها في تطبيقك، يمكنك الاستفادة من الدمج وACTION_CANCEL.

راجِع أيضًا مقالة رفض راحة اليد والتنقّل والإدخالات غير المرغوب فيها أعلاه.

يمكنك استخدام طريقة setSystemBarsBehavior() وBEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE من WindowInsetsController لمنع إيماءات التنقل من التسبب في أحداث اللمس غير المرغوب فيها:

Kotlin

// Configure the behavior of the hidden system bars.
windowInsetsController.systemBarsBehavior =
    WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE

Java

// Configure the behavior of the hidden system bars.
windowInsetsController.setSystemBarsBehavior(
    WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
);

لمزيد من المعلومات عن إدارة الإدخالات والإيماءات، راجع:

وقت الاستجابة السريع

وقت الاستجابة هو الوقت الذي تحتاجه الأجهزة والنظام والتطبيق لمعالجة البيانات التي يُدخلها المستخدم وعرضها.

وقت الاستجابة = معالجة إدخال الأجهزة ونظام التشغيل + معالجة التطبيقات + تركيب النظام + عرض الأجهزة

يؤدي وقت الاستجابة إلى تأخّر الخط المعروض عن موضع قلم الشاشة. تمثل الفجوة بين الحد الخارجي وموضع قلم الشاشة وقت الاستجابة.
الشكل 8. يؤدي وقت الاستجابة إلى تأخّر الخط المعروض عن موضع قلم الشاشة.

مصدر وقت الاستجابة

  • تسجيل قلم الشاشة باستخدام الشاشة التي تعمل باللمس (الأجهزة): اتصال لاسلكي مبدئي عندما يتصل قلم الشاشة ونظام التشغيل ليتم تسجيلهما ومزامنتهما.
  • معدل أخذ عينات اللمس (الأجهزة): عدد المرات في الثانية التي تعمل فيها الشاشة التي تعمل باللمس للتحقق مما إذا كان مؤشر ملامسًا للسطح، ويتراوح من 60 إلى 1000 هرتز.
  • معالجة الإدخال (التطبيق): تطبيق اللون وتأثيرات الرسومات والتحويل على البيانات التي أدخلها المستخدم.
  • عرض الرسومات (نظام التشغيل + الأجهزة): تبديل التخزين المؤقت ومعالجة الأجهزة

رسومات بوقت استجابة سريع

تعمل مكتبة رسومات Jetpack ذات الاستجابة السريعة على تقليل وقت المعالجة بين البيانات التي يدخلها المستخدم والعرض على الشاشة.

تقلِّل المكتبة من وقت المعالجة من خلال تجنُّب العرض باستخدام مخزن مؤقّت متعدد والاستفادة من أسلوب عرض المخزن المؤقت الأمامي، ما يعني الكتابة مباشرةً على الشاشة.

عرض المخزن المؤقت الأمامي

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

يكتب التطبيق إلى المخزن المؤقت للشاشة ويقرأ من المخزن المؤقت للشاشة.
الشكل 9. عرض المخزن المؤقت الأمامي
يكتب التطبيق إلى المخزن المؤقت المتعدد، والذي يستبدل بمخزن مؤقت للشاشة. يقرأ التطبيق من المخزن المؤقت للشاشة.
الشكل 10. عرض المخزن المؤقت المتعدد

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

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

التبعيات

توفّر المكتبة ذات وقت الاستجابة السريع المكوّنات اللازمة لتنفيذ عرض المخزن المؤقت الأمامي. تتم إضافة المكتبة كمكتبة تبعية في ملف build.gradle الخاص بوحدة التطبيق:

dependencies {
    implementation "androidx.graphics:graphics-core:1.0.0-alpha03"
}

استدعاءات GLFrontBufferRenderer

تتضمن مكتبة وقت الاستجابة السريع واجهة GLFrontBufferRenderer.Callback التي تحدّد الطرق التالية:

لا تراعي المكتبة التي تتسم بالاستجابة السريعة نوع البيانات التي تستخدمها مع GLFrontBufferRenderer.

ومع ذلك، تعالج المكتبة البيانات كتدفق لمئات نقاط البيانات؛ وبالتالي، صمم بياناتك لتحسين استخدام الذاكرة وتخصيصها.

عمليات معاودة الاتصال

لتفعيل عرض عمليات معاودة الاتصال، عليك تنفيذ GLFrontBufferedRenderer.Callback وإلغاء onDrawFrontBufferedLayer() وonDrawDoubleBufferedLayer(). يستخدم تطبيق "GLFrontBufferedRenderer" عمليات معاودة الاتصال لعرض بياناتك بأفضل طريقة ممكنة.

Kotlin

val callback = object: GLFrontBufferedRenderer.Callback<DATA_TYPE> {

   override fun onDrawFrontBufferedLayer(
       eglManager: EGLManager,
       bufferInfo: BufferInfo,
       transform: FloatArray,
       param: DATA_TYPE
   ) {
       // OpenGL for front buffer, short, affecting small area of the screen.
   }

   override fun onDrawMultiDoubleBufferedLayer(
       eglManager: EGLManager,
       bufferInfo: BufferInfo,
       transform: FloatArray,
       params: Collection<DATA_TYPE>
   ) {
       // OpenGL full scene rendering.
   }
}

Java

GLFrontBufferedRenderer.Callback<DATA_TYPE> callbacks =
    new GLFrontBufferedRenderer.Callback<DATA_TYPE>() {
        @Override
        public void onDrawFrontBufferedLayer(@NonNull EGLManager eglManager,
            @NonNull BufferInfo bufferInfo,
            @NonNull float[] transform,
            DATA_TYPE data_type) {
                // OpenGL for front buffer, short, affecting small area of the screen.
        }

    @Override
    public void onDrawDoubleBufferedLayer(@NonNull EGLManager eglManager,
        @NonNull BufferInfo bufferInfo,
        @NonNull float[] transform,
        @NonNull Collection<? extends DATA_TYPE> collection) {
            // OpenGL full scene rendering.
    }
};
تعريف مثيل من GLFrontBufferedRenderer

يمكنك إعداد GLFrontBufferedRenderer من خلال تقديم SurfaceView وعمليات معاودة الاتصال التي أنشأتها سابقًا. يحسّن GLFrontBufferedRenderer العرض أمام الكاميرا الأمامية والتخزين المؤقت المزدوج باستخدام عمليات معاودة الاتصال:

Kotlin

var glFrontBufferRenderer = GLFrontBufferedRenderer<DATA_TYPE>(surfaceView, callbacks)

Java

GLFrontBufferedRenderer<DATA_TYPE> glFrontBufferRenderer =
    new GLFrontBufferedRenderer<DATA_TYPE>(surfaceView, callbacks);
العرض

يبدأ عرض المخزن المؤقت الأمامي عند طلب الإجراء renderFrontBufferedLayer()، ما يؤدي إلى ظهور استدعاء onDrawFrontBufferedLayer().

يتم استئناف العرض بالتخزين المؤقت عند استدعاء الدالة commit()، ما يؤدي إلى تشغيل استدعاء onDrawMultiDoubleBufferedLayer().

في المثال التالي، يتم عرض العملية على المخزن المؤقت الأمامي (العرض السريع) عندما يبدأ المستخدم الرسم على الشاشة (ACTION_DOWN) ويحرّك المؤشر حولها (ACTION_MOVE). ويتم عرض العملية في المخزن المؤقت المزدوج عندما يغادر المؤشر سطح الشاشة (ACTION_UP).

يمكنك استخدام requestUnbufferedDispatch() للطلب من نظام الإدخال عدم تجميع أحداث الحركة، ولكن بدلاً من ذلك عرضها فور توفُّرها:

Kotlin

when (motionEvent.action) {
   MotionEvent.ACTION_DOWN -> {
       // Deliver input events as soon as they arrive.
       view.requestUnbufferedDispatch(motionEvent)
       // Pointer is in contact with the screen.
       glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE)
   }
   MotionEvent.ACTION_MOVE -> {
       // Pointer is moving.
       glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE)
   }
   MotionEvent.ACTION_UP -> {
       // Pointer is not in contact in the screen.
       glFrontBufferRenderer.commit()
   }
   MotionEvent.CANCEL -> {
       // Cancel front buffer; remove last motion set from the screen.
       glFrontBufferRenderer.cancel()
   }
}

Java

switch (motionEvent.getAction()) {
   case MotionEvent.ACTION_DOWN: {
       // Deliver input events as soon as they arrive.
       surfaceView.requestUnbufferedDispatch(motionEvent);

       // Pointer is in contact with the screen.
       glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE);
   }
   break;
   case MotionEvent.ACTION_MOVE: {
       // Pointer is moving.
       glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE);
   }
   break;
   case MotionEvent.ACTION_UP: {
       // Pointer is not in contact in the screen.
       glFrontBufferRenderer.commit();
   }
   break;
   case MotionEvent.ACTION_CANCEL: {
       // Cancel front buffer; remove last motion set from the screen.
       glFrontBufferRenderer.cancel();
   }
   break;
}

الإجراءات المسموحة وغير المسموح بها للعرض

الإجراءات المقترَحة

أجزاء صغيرة من الشاشة والكتابة بخط اليد والرسم والرسم التخطيطي.

الإجراءات التي لا يُنصح بها

تحديث بملء الشاشة، عرض شامل، تكبير/تصغير. قد يؤدي إلى تمزيق الجهاز.

تمزيق

يحدث تمزيق الشاشة عند تحديث الشاشة أثناء تعديل المخزن المؤقت للشاشة في الوقت نفسه. يعرض جزء من الشاشة البيانات الجديدة، بينما يعرض جزء آخر البيانات القديمة.

عدم محاذاة الأجزاء العلوية والسفلية من صورة Android بسبب حدوث تمزيق أثناء تحديث الشاشة.
الشكل 11. الدموع أثناء إعادة تحميل الشاشة من أعلى إلى أسفل.

التنبؤ بالحركة

تعمل مكتبة توقُّع حركة Jetpack على تقليل وقت الاستجابة الملحوظ من خلال تقدير مسار حركة المستخدم وتوفير نقاط زائفة ومؤقتة لبرنامج العرض.

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

عناصر MotionEvent المتوقّعة هي مجرد تقديرات. يمكن أن تؤدي الأحداث المتوقّعة إلى تقليل وقت الاستجابة الملحوظ، ولكن يجب استبدال البيانات المتوقّعة ببيانات MotionEvent الفعلية بعد تلقّيها.

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

يؤدي وقت الاستجابة إلى تأخّر الخط المعروض عن موضع قلم الشاشة. تمتلئ الفجوة بين الحد الخارجي وقلم الشاشة بنقاط التنبؤ. الفجوة المتبقية هي وقت الاستجابة المحسوس.
الشكل 12. يتم تقليل وقت الاستجابة بسبب التنبؤ بالحركة.

التبعيات

توفر مكتبة التنبؤ بالحركة تنفيذ التنبؤ. تتم إضافة المكتبة كمكتبة تبعية في ملف build.gradle الخاص بوحدة التطبيق:

dependencies {
    implementation "androidx.input:input-motionprediction:1.0.0-beta01"
}

التنفيذ

تتضمن مكتبة توقّعات الحركة واجهة MotionEventPredictor التي تُحدِّد الطرق التالية:

  • record(): يتم تخزين عناصر MotionEvent كسجلّ لإجراءات المستخدم.
  • predict(): عرض MotionEvent متوقّع
توضيح مثيل من MotionEventPredictor

Kotlin

var motionEventPredictor = MotionEventPredictor.newInstance(view)

Java

MotionEventPredictor motionEventPredictor = MotionEventPredictor.newInstance(surfaceView);
إطعام المتنبئ بالبيانات

Kotlin

motionEventPredictor.record(motionEvent)

Java

motionEventPredictor.record(motionEvent);
التنبؤ

Kotlin

when (motionEvent.action) {
   MotionEvent.ACTION_MOVE -> {
       val predictedMotionEvent = motionEventPredictor?.predict()
       if(predictedMotionEvent != null) {
            // use predicted MotionEvent to inject a new artificial point
       }
   }
}

Java

switch (motionEvent.getAction()) {
   case MotionEvent.ACTION_MOVE: {
       MotionEvent predictedMotionEvent = motionEventPredictor.predict();
       if(predictedMotionEvent != null) {
           // use predicted MotionEvent to inject a new artificial point
       }
   }
   break;
}

الإجراءات المستحسنة والإجراءات غير المستحسنة في التنبؤ بالحركة

الإجراءات المقترَحة

إزالة نقاط التوقّع عند إضافة نقطة توقّع جديدة

الإجراءات التي لا يُنصح بها

ولا تستخدِم نقاط التوقّع للعرض النهائي.

تطبيقات تدوين الملاحظات

يتيح نظام التشغيل ChromeOS لتطبيقك توضيح بعض إجراءات تدوين الملاحظات.

لتسجيل تطبيق كتطبيق تدوين ملاحظات على نظام التشغيل ChromeOS، يُرجى الاطّلاع على توافق الإدخال.

لتسجيل تطبيق كتدوين ملاحظات على Android، راجع إنشاء تطبيق تدوين ملاحظات.

لقد قدّم نظام Android 14 (مستوى واجهة برمجة التطبيقات 34) الغرض من ACTION_CREATE_NOTE الذي يتيح لتطبيقك بدء نشاط تدوين الملاحظات على شاشة القفل.

التعرّف على الحبر الرقمي باستخدام أدوات تعلّم الآلة

باستخدام التعرّف على الحبر الرقمي لـ ML Kit، يمكن لتطبيقك التعرّف على النص المكتوب بخط اليد على سطح رقمي بمئات اللغات. يمكنك أيضًا تصنيف الرسومات.

توفّر "حزمة تعلّم الآلة" للصف Ink.Stroke.Builder لإنشاء عناصر Ink يمكن معالجتها باستخدام نماذج تعلُّم الآلة لتحويل الكتابة بخط اليد إلى نص.

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

راجِع التعرُّف على الحبر الرقمي للاطّلاع على مزيد من المعلومات.

مراجع إضافية

أدلة المطوِّرين

الدروس التطبيقية حول الترميز