على الأجهزة ذات الشاشات الكبيرة، يتفاعل المستخدمون غالبًا مع التطبيقات باستخدام لوحة مفاتيح أو ماوس أو لوحة تتبُّع أو قلم شاشة أو عصا تحكّم. للسماح لتطبيقك بقبول الإدخال من الأجهزة الخارجية، اتّبِع الخطوات التالية:
- اختبار إمكانية استخدام لوحة المفاتيح الأساسية، مثل Ctrl+Z للتراجع وCtrl+C للنسخ وCtrl+S للحفظ اطّلِع على التعامل مع إجراءات لوحة المفاتيح للحصول على قائمة باختصارات لوحة المفاتيح التلقائية.
- اختبار التوافق مع لوحة المفاتيح المتقدّمة، على سبيل المثال، التنقّل باستخدام مفتاح Tab ومفاتيح الأسهم، وتأكيد إدخال النص باستخدام مفتاح Enter، وتشغيل الوسائط وإيقافها مؤقتًا باستخدام مفتاح المسافة في تطبيقات الوسائط
- اختبار التفاعلات الأساسية مع الماوس، بما في ذلك النقر بزر الماوس الأيمن لعرض قائمة السياق، وتغييرات الرموز عند التمرير فوقها، وأحداث التمرير باستخدام عجلة الماوس أو لوحة اللمس على المكوّنات المخصّصة
- اختبار أجهزة الإدخال الخاصة بالتطبيقات، مثل القلم الرقمي وأذرع التحكّم في الألعاب وأذرع التحكّم في MIDI الخاصة بتطبيقات الموسيقى
- يمكنك توفير إمكانات متقدّمة لإدخال البيانات تساعد في تمييز التطبيق في بيئات سطح المكتب، مثل استخدام لوحة اللمس كأداة لتخفيف الصوت تدريجيًا في تطبيقات الدي جي، وإمكانية استخدام الماوس في الألعاب، واختصارات لوحة المفاتيح للمستخدمين الذين يفضّلون استخدام لوحة المفاتيح.
لوحة المفاتيح
تساهم طريقة استجابة تطبيقك لإدخال البيانات باستخدام لوحة المفاتيح في تحسين تجربة المستخدم على الشاشة الكبيرة. هناك ثلاثة أنواع من إدخال لوحة المفاتيح: التنقل وضغطات المفاتيح والاختصارات.
التنقل
لا يتم عادةً توفير إمكانية التنقّل باستخدام لوحة المفاتيح في التطبيقات التي تركّز على اللمس، ولكن يتوقّع المستخدمون توفّرها عند استخدام تطبيق ولديهم لوحة مفاتيح. قد يكون التنقّل باستخدام لوحة المفاتيح ضروريًا على الهواتف والأجهزة اللوحية والهواتف القابلة للطي وأجهزة الكمبيوتر المكتبي للمستخدمين الذين لديهم احتياجات متعلّقة بتسهيل الاستخدام.
في العديد من التطبيقات، يتم التعامل مع التنقّل باستخدام مفتاحَي السهم وTab تلقائيًا من خلال إطار عمل Android. على سبيل المثال، يمكن التركيز على بعض الدوال المركّبة تلقائيًا، مثل 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 عملية ربط تنقّل لجميع المكوّنات القابلة للتركيز استنادًا إلى موضعها. عادةً ما يعمل هذا الإجراء على النحو المتوقّع ولا يلزم إجراء أي تطوير إضافي.
ومع ذلك، لا يحدّد Compose دائمًا العنصر التالي الصحيح للتنقّل باستخدام علامات التبويب في العناصر القابلة للإنشاء المعقّدة، مثل علامات التبويب والقوائم، على سبيل المثال، عندما يكون أحد العناصر القابلة للإنشاء قابلاً للتمرير أفقيًا وغير مرئي بالكامل.
للتحكّم في سلوك التركيز، أضِف عنصر تعديل 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") }
}
}
لمزيد من المعلومات، يُرجى الاطّلاع على توفير تنقّل متسق باستخدام مجموعات التركيز.
اختبِر إمكانية الوصول إلى كل عنصر في واجهة المستخدم في تطبيقك باستخدام لوحة المفاتيح فقط. يجب أن تكون العناصر المستخدَمة بشكل متكرر قابلة للوصول إليها بدون استخدام الماوس أو اللمس.
تذكَّر أنّ إتاحة استخدام لوحة المفاتيح قد تكون ضرورية للمستخدمين الذين لديهم احتياجات متعلّقة بتسهيل الاستخدام.
ضغطات المفاتيح
بالنسبة إلى إدخال النصوص التي ستتعامل معها لوحة مفاتيح افتراضية على الشاشة (محرّك أسلوب الإدخال)،
مثل
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() وإضافة السلوك المتوقّع لكل رمز مفتاح تم تلقّيه:
kotlin
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 مع طريقة تعالج أحداث الحركة، ثم مرِّر الطريقة كدالة lambda 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 فقط. في نظام التشغيل Android 13 (المستوى 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
- سجِّل الخروج، ثم أعِد تسجيل الدخول
من المفترض أن تظهر قائمة القلم الآن على الرف:
- انقر على زر القلم على الرف واختَر ملاحظة جديدة. سيؤدي ذلك إلى فتح ملاحظة رسم فارغة.
- خُذ لقطة شاشة. من الرف، انقر على زر القلم > تصوير الشاشة أو نزِّل صورة. يجب أن يظهر الخيار إضافة تعليق توضيحي إلى الصورة في الإشعار. من المفترض أن يؤدي ذلك إلى تشغيل التطبيق مع عرض الصورة الجاهزة للتعليق.
إمكانية استخدام الماوس ولوحة اللمس
بشكل عام، تحتاج معظم التطبيقات إلى التعامل مع ثلاثة أحداث فقط تركّز على الشاشات الكبيرة، وهي: النقر بزر الماوس الأيمن والتمرير والسحب والإفلات.
النقر بزر الماوس الأيمن
يجب أن تتفاعل أيضًا أي إجراءات تؤدي إلى عرض قائمة سياق في التطبيق، مثل النقر مع الاستمرار على عنصر في القائمة، مع أحداث النقر بزر الماوس الأيمن.
للتعامل مع أحداث النقر بزر الماوس الأيمن، يجب أن تسجّل التطبيقات
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" />