على الأجهزة ذات الشاشات الكبيرة، يتفاعل المستخدمون غالبًا مع التطبيقات باستخدام لوحة مفاتيح أو ماوس أو لوحة لمس أو قلم شاشة أو ذراع تحكم. لتفعيل تطبيقك لقبول الإدخال من devices الخارجية، اتّبِع الخطوات التالية:
- اختبار وظائف لوحة المفاتيح الأساسية، مثل Ctrl+Z للتراجع، Ctrl+C للنسخ، وCtrl+S للحفظ اطّلِع على معالجة إجراءات لوحة المفاتيح للحصول على قائمة باختصارات لوحة المفاتيح التلقائية.
- اختبِر ميزات لوحة المفاتيح المتقدّمة، مثل مفتاح التبويب (Tab) و التنقّل باستخدام مفاتيح الأسهم، وتأكيد إدخال النص باستخدام مفتاح Enter، واستخدام مفتاح المسافة للتشغيل والإيقاف المؤقت في تطبيقات الوسائط.
- اختبار التفاعلات الأساسية باستخدام الماوس، بما في ذلك النقر بزر الماوس الأيمن لعرض القائمة السياقية، وتغييرات الرموز عند التمرير بمؤشر الماوس، وأحداث التمرير باستخدام عجلة الماوس أو لوحة اللمس في المكونات المخصّصة
- اختبار أجهزة الإدخال الخاصة بالتطبيق، مثل قلم الشاشة ووحدات التحكّم في الألعاب و وحدات التحكّم MIDI لتطبيقات الموسيقى
- ننصحك بتوفير ميزات متقدّمة لإدخال البيانات يمكن أن تجعل التطبيق بارزًا في بيئات أجهزة الكمبيوتر المكتبي، مثل استخدام لوحة اللمس كأداة تمويه في تطبيقات دي جي، واستخدام الماوس لالتقاط العناصر في الألعاب، واختصارات لوحة المفاتيح لمستخدمي لوحة المفاتيح.
لوحة المفاتيح
تساهم طريقة استجابة تطبيقك لإدخالات لوحة المفاتيح في تحسين تجربته على الشاشة الكبيرة. هناك ثلاثة أنواع من إدخالات لوحة المفاتيح: التنقّل، ضغطات المفاتيح، والاختصارات.
التنقّل
نادرًا ما يتم استخدام ميزة التنقّل باستخدام لوحة المفاتيح في التطبيقات التي تركّز على اللمس، ولكن يتوقعها المستخدمون عند استخدام تطبيق ووضع أيديهم على لوحة مفاتيح. يمكن أن يكون التنقّل باستخدام لوحة المفاتيح أساسيًا على الهواتف والأجهزة اللوحية والأجهزة القابلة للطي وأجهزة الكمبيوتر المكتبي للمستخدمين الذين يحتاجون إلى تسهيل الاستخدام.
في العديد من التطبيقات، يعالج إطار عمل Android تلقائيًا عملية التنقّل باستخدام مفتاحَي الأسهم ومفتاح Tab. على سبيل المثال، يمكن توجيه التركيز تلقائيًا إلى بعض العناصر القابلة للتجميع، مثل Button
أو عنصر قابل للتجميع يتضمّن المُعدِّل
clickable
، ومن المفترض أن تعمل ميزة التنقّل باستخدام لوحة المفاتيح بشكل عام بدون أي رمز برمجي إضافي. لتفعيل التنقّل باستخدام لوحة المفاتيح للعناصر المخصّصة التي
لا يمكن التركيز عليها تلقائيًا، أضِف المُعدِّل focusable
:
var color by remember { mutableStateOf(Green) } Box( Modifier .background(color) .onFocusChanged { color = if (it.isFocused) Blue else Green } .focusable() ) { Text("Focusable 1") }
لمزيد من المعلومات، يُرجى الاطّلاع على إتاحة التركيز على عنصر قابل للتجميع.
عند تفعيل التركيز، ينشئ إطار عمل Android تعيينًا للتنقّل في جميع المكوّنات التي يمكن التركيز عليها استنادًا إلى مواضعها. يعمل هذا الإجراء عادةً على النحو المتوقّع، ولا يلزم إجراء أي تعديلات إضافية.
ومع ذلك، لا تحدِّد ميزة "الإنشاء" دائمًا العنصر التالي الصحيح للتنقّل في علامة التبويب للعناصر المُركّبة المعقدة، مثل علامات التبويب والقوائم، على سبيل المثال، عندما يكون أحد العناصر المُركّبة عنصرًا قابلاً للانتقال أفقيًا غير مرئي بالكامل.
للتحكّم في سلوك التركيز، أضِف المُعدِّل focusGroup
إلى العنصر المكوّن
الرئيسي لمجموعة من العناصر المكوّنة. يتم نقل التركيز إلى المجموعة، ثم
من خلال المجموعة قبل الانتقال إلى المكوّن التالي القابل للتركيز، على سبيل المثال:
Row {
Column(Modifier.focusGroup()) {
Button({}) { Text("Row1 Col1") }
Button({}) { Text("Row2 Col1") }
Button({}) { Text("Row3 Col1") }
}
Column(Modifier.focusGroup()) {
Button({}) { Text("Row1 Col2") }
Button({}) { Text("Row2 Col2") }
Button({}) { Text("Row3 Col2") }
}
}
لمزيد من المعلومات، يُرجى الاطّلاع على توفير تنقّل متّسق باستخدام مجموعات التركيز.
اختبِر إمكانية الوصول إلى كل عنصر من عناصر واجهة المستخدم في تطبيقك باستخدام لوحة المفاتيح فقط. يجب أن تكون العناصر المُستخدَمة بكثرة متاحة بدون استخدام الماوس أو الإدخال باللمس.
تذكَّر أنّ إتاحة لوحة المفاتيح قد يكون أمرًا ضروريًا للمستخدمين الذين لديهم احتياجات تتعلّق بتسهيل الاستخدام.
ضغطات المفاتيح
بالنسبة إلى إدخال النصوص التي ستتم معالجتها بواسطة لوحة مفاتيح افتراضية على الشاشة (IME)،
مثل
TextField
، يجب أن تعمل التطبيقات على النحو المتوقّع على الأجهزة ذات الشاشات الكبيرة بدون أي جهد إضافي في تطويرها. بالنسبة إلى ضغطات المفاتيح التي لا يمكن للإطار المتّبع توقّعها،
على التطبيقات معالجة السلوك بنفسها. وينطبق ذلك بشكل خاص على التطبيقات التي توفّر ملفّات تعريف مخصّصة.
تشمل الأمثلة على ذلك تطبيقات المحادثة التي تستخدم مفتاح Enter لإرسال رسالة، وتطبيقات الوسائط التي تبدأ تشغيل المحتوى وتوقِفه باستخدام مفتاح المسافة، والألعاب التي تتحكّم في الحركة باستخدام مفاتيح w وa وs و d.
يمكنك معالجة ضغطات المفاتيح الفردية باستخدام المُعدِّل onKeyEvent
الذي
يقبل دالة lambda التي يتمّ استدعاؤها عندما يتلقّى المكوّن المعدَّل حدثًا للمفتاح.
تتيح لك السمة KeyEvent#type
تحديد ما إذا كان الحدث هو
ضغطة مفتاح (KeyDown
) أو رفع إصبع عن مفتاح (KeyUp
):
Box(
modifier = Modifier.focusable().onKeyEvent {
if(
it.type == KeyEventType.KeyUp &&
it.key == Key.S
) {
doSomething()
true
} else {
false
}
}
) {
Text("Press S key")
}
بدلاً من ذلك، يمكنك إلغاء طلب إعادة الاتصال onKeyUp()
وإضافة السلوك المُتوقَّع لكل رمز مفتاح تم استلامه:
override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { return when (keyCode) { KeyEvent.KEYCODE_ENTER -> { sendChatMessage() true } KeyEvent.KEYCODE_SPACE -> { playOrPauseMedia() true } else -> super.onKeyUp(keyCode, event) } }
يحدث الحدث onKeyUp
عند رفع إصبع المستخدم عن مفتاح. يمنع استخدام دالة الاستدعاء
التطبيقات من الحاجة إلى معالجة أحداث onKeyDown
متعددة في حال الضغط على مفتاح
أو تحريره ببطء. إنّ الألعاب والتطبيقات التي تحتاج إلى رصد لحظة الضغط على
مفتاح أو ما إذا كان المستخدم يضغط باستمرار على مفتاح معيّن يمكنها الاستماع إلى حدث
onKeyDown
ومعالجة أحداث onKeyDown
المتكرّرة بنفسها.
لمزيد من المعلومات، يُرجى الاطّلاع على معالجة إجراءات لوحة المفاتيح.
الاختصارات
من المتوقّع أن تعمل اختصارات لوحة المفاتيح الشائعة التي تتضمّن مفاتيح Ctrl وAlt Shift وMeta عند استخدام لوحة مفاتيح أجهزة. إذا لم ينفِّذ التطبيق اختصارات، قد تبدو التجربة محبطة للمستخدمين. ويُقدّر المستخدمون المتقدّمون أيضًا الاختصارات للمهام المتعلّقة بالتطبيق والتي يتم استخدامها بشكل متكرر. تجعل الاختصارات استخدام التطبيق أسهل، كما تُميّزه عن التطبيقات التي لا تتضمّن اختصارات.
تشمل بعض الاختصارات الشائعة Ctrl+S (حفظ) وCtrl+Z (التراجع) وCtrl+Shift+Z (إعادة). للحصول على قائمة بالاختصارات التلقائية، راجِع معالجة إجراءات لوحة المفاتيح.
يحتوي عنصر KeyEvent
على السمات التالية التي تشير إلى ما إذا كان
يتم الضغط على مفاتيح الترميز:
مثلاً:
Box(
Modifier.onKeyEvent {
if (it.isAltPressed && it.key == Key.A) {
println("Alt + A is pressed")
true
} else {
false
}
}
.focusable()
)
لمزيد من المعلومات، يُرجى الاطّلاع على ما يلي:
قلم الشاشة
تأتي العديد من الأجهزة ذات الشاشات الكبيرة مزوّدة بقلم شاشة. تتعامل تطبيقات Android مع أقلام الشاشة على أنّها إدخالات من شاشة اللمس. قد تتضمّن بعض الأجهزة أيضًا لوحة رسم USB أو بلوتوث، مثل Wacom Intuos. يمكن لتطبيقات Android تلقّي الإدخال عبر البلوتوث ، ولكن لا يمكنها تلقّي الإدخال عبر USB.
للوصول إلى عناصر قلم الرصاص MotionEvent
، أضِف المُعدِّل pointerInteropFilter
إلى سطح الرسم. نفِّذ فئة ViewModel
تتضمّن طريقة تعالج أحداث الحركة، ثم مرِّر الطريقة على أنّها دالة لامدا onTouchEvent
لمعدِّل
pointerInteropFilter
:
@Composable
@OptIn(ExperimentalComposeUiApi::class)
fun DrawArea(modifier: Modifier = Modifier) {
Canvas(modifier = modifier
.clipToBounds()
.pointerInteropFilter {
viewModel.processMotionEvent(it)
}
) {
// Drawing code here.
}
}
يحتوي عنصر MotionEvent
على معلومات عن الحدث:
- يعرض الرمز
MotionEvent#getToolType()
الرمزTOOL_TYPE_FINGER
أوTOOL_TYPE_STYLUS
أوTOOL_TYPE_ERASER
استنادًا إلى الأداة التي تلامست مع الشاشة. MotionEvent#getPressure()
يُبلِغ عن الضغط المادي الذي يتم تطبيقه على قلم الشاشة (إذا كان ذلك متاحًا)MotionEvent#getAxisValue()
معMotionEvent.AXIS_TILT
وMotionEvent.AXIS_ORIENTATION
لتحديد الإمالة والاتجاه الماديين لقلم الشاشة (في حال توفّر ذلك)
النقاط السابقة
يُجمِّع Android أحداث الإدخال ويرسلها مرة واحدة لكل إطار. يمكن للقلم الإلكتروني
الإبلاغ عن الأحداث بمعدّلات تكرار أعلى بكثير من الشاشة. عند إنشاء
تطبيقات للرسم، تحقَّق من الأحداث التي قد تكون حدثت مؤخرًا باستخدام واجهات برمجة التطبيقات التالية في
getHistorical
:
MotionEvent#getHistoricalX()
MotionEvent#getHistoricalY()
MotionEvent#getHistoricalPressure()
MotionEvent#getHistoricalAxisValue()
رفض صورة النخيل
عندما يرسم المستخدمون أو يكتبون أو يتفاعلون مع تطبيقك باستخدام قلم الشاشة، يمسهم أحيانًا
براحة أيديهم على الشاشة. يمكن الإبلاغ عن حدث اللمس (الذي تم ضبطه على
ACTION_DOWN
أو ACTION_POINTER_DOWN
) إلى تطبيقك
قبل أن يرصد النظام لمسة راحة اليد غير المقصودة ويتجاهلها.
يلغي Android أحداث لمسة راحة اليد من خلال إرسال MotionEvent
. إذا تلقّى
تطبيقك الرمز ACTION_CANCEL
، ألغِ الإيماءة. إذا تلقّى تطبيقك رمز العميل
ACTION_POINTER_UP
، تحقّق مما إذا كان قد تم ضبط FLAG_CANCELED
. إذا كان الأمر كذلك، ألغِ
الحركة.
لا تبحث عن FLAG_CANCELED
فقط. في الإصدار 13 من نظام التشغيل Android (المستوى 33 لواجهة برمجة التطبيقات) والإصدارات الأحدث،
يضبط النظام العلامة FLAG_CANCELED
لأحداث ACTION_CANCEL
، ولكن لا يضبط النظام العلامة على إصدارات Android الأقدم.
Android 12
في نظام التشغيل Android 12 (المستوى 32 لواجهة برمجة التطبيقات) والإصدارات الأقدم، يمكن رصد ميزة رفض راحة اليد
فقط لأحداث اللمس باستخدام مؤشر واحد. إذا كان لمسة راحة اليد هي المؤشر الوحيد،
يلغي النظام الحدث من خلال ضبط ACTION_CANCEL
على عنصر
حدث الحركة. إذا كانت المؤشرات الأخرى غير نشطة، يضبط النظام ACTION_POINTER_UP
، وهو
غير كافٍ لرصد رفض راحة اليد.
Android 13
في الإصدار 13 من نظام التشغيل Android (المستوى 33 لواجهة برمجة التطبيقات) والإصدارات الأحدث، إذا كانت لمسة راحة اليد هي المؤشر الوحيد،
يلغي النظام الحدث من خلال ضبط ACTION_CANCEL
وFLAG_CANCELED
في
عنصر حدث الحركة. إذا كانت المؤشرات الأخرى غير نشطة، يضبط النظام
ACTION_POINTER_UP
وFLAG_CANCELED
.
عندما يتلقّى تطبيقك حدثًا متعلّقًا بالحركة مع ACTION_POINTER_UP
، تحقّق من
FLAG_CANCELED
لتحديد ما إذا كان الحدث يشير إلى رفض راحة اليد (أو
إلغاء حدث آخر).
تطبيقات تدوين الملاحظات
يحتوي ChromeOS على نية خاصة تعرِض تطبيقات تدوين الملاحظات المسجَّلة أمام المستخدِمين. لتسجيل تطبيق كمحرِّر ملاحظات، أضِف ما يلي إلى بيان تطبيقك:
<intent-filter>
<action android:name="org.chromium.arc.intent.action.CREATE_NOTE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
عند تسجيل تطبيق في النظام، يمكن للمستخدم اختياره كتطبيق كتابة الملاحظات التلقائي. عند طلب ملاحظة جديدة، من المفترض أن ينشئ التطبيق ملاحظة فارغة جاهزة لإدخالها باستخدام قلم الشاشة. عندما يريد المستخدم إضافة تعليق توضيحي إلى صورة
(مثل لقطة شاشة أو صورة تم تنزيلها)، يتم تشغيل التطبيق باستخدام ClipData
التي تحتوي على عنصر واحد أو أكثر من معرّفات الموارد المنتظمة content://
. يجب أن ينشئ التطبيق ملاحظة تستخدم أول صورة مرفقة كصورة خلفية ويدخل في وضع يمكن فيه للمستخدم الرسم على الشاشة باستخدام قلم شاشة.
اختبار نوايا تدوين الملاحظات بدون قلم شاشة
[سيتم إزالة هذا القسم لاحقًا.]
لاختبار ما إذا كان التطبيق يستجيب بشكل صحيح لطلبات تدوين الملاحظات بدون استخدام قلم نشط، استخدِم الطريقة التالية لعرض خيارات تدوين الملاحظات على ChromeOS:
- التبديل إلى وضع المطوّر وضبط الجهاز على وضع الكتابة
- اضغط على Ctrl+Alt+F2 لفتح وحدة طرفية.
- نفِّذ الأمر
sudo vi /etc/chrome_dev.conf
. - اضغط على
i
لتعديل--ash-enable-palette
وإضافته إلى سطر جديد في نهاية الملف. - احفظ التغييرات بالضغط على Esc ثم كتابة : وw q والضغط على Enter.
- اضغط على Ctrl+Alt+F1 للعودة إلى واجهة مستخدم ChromeOS العادية.
- تسجيل الخروج ثم إعادة تسجيل الدخول
من المفترض أن تظهر الآن قائمة قلم الشاشة على الرف:
- انقر على زر قلم الشاشة في الرف واختر ملاحظة جديدة. من المفترض أن يؤدي ذلك إلى فتح ملاحظة رسم فارغة.
- خذ لقطة شاشة. من الرف، انقر على زر قلم الشاشة > التقاط شاشة أو نزِّل صورة. من المفترض أن يتوفّر خيار إضافة تعليقات توضيحية إلى الصورة في الإشعار. من المفترض أن يؤدي ذلك إلى تشغيل التطبيق مع الصورة الجاهزة لإضافة annotations إليها.
إتاحة الماوس ولوحة اللمس
لا تحتاج معظم التطبيقات بشكل عام إلى معالجة سوى ثلاثة أحداث تركّز على الشاشة الكبيرة: النقر بزر الماوس الأيمن والمرّر بمؤشر الماوس والسحب والإسقاط.
النقر بزر الماوس الأيمن
يجب أن تستجيب أيضًا أي إجراءات تؤدي إلى عرض قائمة سياقات في التطبيق، مثل النقر مع الاستمرار على أحد عناصر القائمة، لأحداث النقر بزر الماوس الأيمن.
لمعالجة أحداث النقر بزر الماوس الأيمن، يجب أن تسجِّل التطبيقات
View.OnContextClickListener
:
Box(modifier = Modifier.fillMaxSize()) {
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { context ->
val rootView = FrameLayout(context)
val onContextClickListener =
View.OnContextClickListener { view ->
showContextMenu()
true
}
rootView.setOnContextClickListener(onContextClickListener)
rootView
},
)
}
لمعرفة التفاصيل حول إنشاء قوائم السياقات، يُرجى الاطّلاع على إنشاء قائمة سياقية.
تمرير مؤشر الماوس
يمكنك جعل تصاميم تطبيقك أكثر اتساقًا وسهولة في الاستخدام من خلال التعامل مع أحداث التمرير فوق العناصر. وينطبق ذلك بشكل خاص على المكونات المخصّصة :
في ما يلي المثالان الأكثر شيوعًا على ذلك:
- الإشارة إلى المستخدمين ما إذا كان العنصر يتضمّن سلوكًا تفاعليًا، مثل أن يكون قابلاً للنقر أو قابلاً للتعديل، من خلال تغيير رمز مؤشر الماوس
- إضافة ملاحظات مرئية إلى العناصر في قائمة أو شبكة كبيرة عند التمرير فوقها
سحب وإفلات
في بيئة متعددة النوافذ، يتوقع المستخدمون أن يتمكّنوا من سحب العناصر وإفلاتها بين التطبيقات. وينطبق ذلك على أجهزة الكمبيوتر المكتبي بالإضافة إلى الأجهزة اللوحية والهواتف والأجهزة المزوّدة بشاشة قابلة للطي في وضع تقسيم الشاشة.
يجب النظر في ما إذا كان من المرجّح أن يسحب المستخدمون عناصر إلى تطبيقك. على سبيل المثال، يجب أن يتوقّع محرّرو الصور تلقّي صور، ويجب أن يتوقّع مشغّلو الموسيقى تلقّي ملفات صوتية، ويجب أن يتوقّع برامج الرسم تلقّي صور.
لإضافة ميزة السحب والإفلات، يُرجى الاطّلاع على مقالة السحب والإفلات ومقالة المدونة Android على ChromeOS: تنفيذ ميزة السحب والإفلات.
اعتبارات خاصة لنظام التشغيل ChromeOS
- تذكَّر طلب الإذن من خلال
requestDragAndDropPermissions()
ل الوصول إلى العناصر التي يتم سحبها من خارج التطبيق. يجب أن يتضمّن العنصر علامة
View.DRAG_FLAG_GLOBAL
لكي تتمكّن من سحبه إلى تطبيقات أخرى.الاطّلاع على بدء حدث سحب
إتاحة مؤشر متقدّم
على التطبيقات التي تعالج بشكل متقدّم إدخالات الماوس ولوحة اللمس استخدام مُعدِّل
pointerInput
للحصول على PointerEvent
:
@Composable private fun LogPointerEvents(filter: PointerEventType? = null) { var log by remember { mutableStateOf("") } Column { Text(log) Box( Modifier .size(100.dp) .background(Color.Red) .pointerInput(filter) { awaitPointerEventScope { while (true) { val event = awaitPointerEvent() // handle pointer event if (filter == null || event.type == filter) { log = "${event.type}, ${event.changes.first().position}" } } } } ) } }
راجِع عنصر PointerEvent
لتحديد ما يلي:
PointerType
: الماوس والقلم والشاشة التي تعمل باللمس وما إلى ذلك منPointerEvent#changes
PointerEventType
: إجراءات المؤشر، مثل الضغط والنقل والانتقال للأسفل/للأعلى والإفلات
أجهزة التحكّم في الألعاب
تتوافق بعض أجهزة Android ذات الشاشات الكبيرة مع ما يصل إلى أربع وحدات تحكّم في الألعاب. استخدِم واجهتَي برمجة التطبيقات المعياريتَين لوحدات تحكّم ألعاب Android من أجل التعامل مع وحدات التحكّم في الألعاب (اطّلِع على إتاحة استخدام وحدات التحكّم في الألعاب).
يتم ربط أزرار وحدة تحكّم الألعاب بقيم شائعة وفقًا لربط شائع. ولكن لا يتّبع جميع المصنّعين اصطلاحات الربط نفسها. يمكنك تقديم تجربة أفضل بكثير إذا سمحت للمستخدمين باختيار تصاميم مختلفة لعناصر التحكّم الشائعة. اطّلِع على معالجة الضغطات على أزرار جهاز التحكّم في الألعاب للحصول على مزيد من المعلومات.
وضع ترجمة الإدخال
يفعّل نظام التشغيل ChromeOS وضع ترجمة الإدخال تلقائيًا. بالنسبة إلى معظم تطبيقات Android، يساعد هذا الوضع التطبيقات على العمل على النحو المتوقّع في بيئة سطح المكتب. تشمل بعض الأمثلة تفعيل التمرير باستخدام إصبعين على لوحة اللمس تلقائيًا، والتمرير باستخدام عجلة الماوس، وربط إحداثيات العرض الأوّلية بإحداثيات النافذة. بشكل عام، لا يحتاج مطوّرو التطبيقات إلى تنفيذ أيّ من هذه السلوكيات بأنفسهم.
إذا كان التطبيق ينفِّذ سلوك إدخال مخصّصًا، على سبيل المثال تحديد إجراء مخصّص للضغط بإصبعَين على لوحة اللمس، أو إذا كانت ترجمات الإدخال هذه لا توفّر أحداث الإدخال المتوقّعة من التطبيق، يمكنك إيقاف وضع ترجمة الإدخال عن طريق إضافة العلامة التالية إلى بيان Android:
<uses-feature
android:name="android.hardware.type.pc"
android:required="false" />