كوتلن متاح للجميع: كتابة كود لا يتخلى عن المستخدمين

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

لماذا إمكانية الوصول في Kotlin هي قوة خارقة وليست مجرد علامة اختيار

\n\n

تخيل: لقد كتبت تطبيقًا رائعًا بلغة Kotlin. تصميم Material جميل، رسوم متحركة سلسة، تدفقات تفاعلية. أنت فخور بالكود. ولكن بعد ذلك يتبين أن شخصًا ضعيف البصر لا يستطيع الضغط على زر "شراء"، لأن TalkBack يقرأه كـ "زر غير مُصنف". أو أن مستخدمًا يعاني من رعشة في اليد يخطئ في التبديل الصغير.

\n\n

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

\n\n

في هذه المقالة، سنشرح كيفية كتابة كود متاح بلغة Kotlin دون ألم. بدون أطنان من الكود النمطي. مع أمثلة حية يمكنك نسخها ولصقها الآن.

\n\n

المبادئ الأساسية: ContentDescription هو أفضل صديق لك

\n\n

أكثر فشل شائع في إمكانية الوصول هو عدم وجود وصف لعناصر الواجهة. نظام TalkBack (قارئ الشاشة على Android) لا يستطيع قراءة الصور أو الأيقونات. إنه يحتاج إلى نص.

\n\n

في Kotlin، يتم ذلك من خلال الخاصية contentDescription. ولكن ليس مجرد "زر"، بل بشكل ذي معنى.

\n\n

مثال سيء (لا تفعل ذلك)

\n
imageView.contentDescription = "زر"
\n\n

مثال جيد

\n
binding.fabAddTask.contentDescription = "إضافة مهمة جديدة"
\n\n

إذا كانت الأيقونة تزيينية (مجرد زخرفة) - قم بتعيين contentDescription = null لتجاهلها من قبل TalkBack.

\n\n
// أيقونة تزيينية - لا نشتت المستخدم\nbinding.decorativeIcon.contentDescription = null
\n\n

نصيحة: استخدم موارد النصوص (strings.xml) لدعم التوطين. لا تقم بترميز النص العربي في ملفات Kotlin.

\n\n

التصنيف الدلالي: إخبار النظام بما هو مهم

\n\n

العناصر القياسية View (Button, TextView) تؤدي المهمة بشكل جيد، لكن المكونات المخصصة غالبًا ما تكسر إمكانية الوصول. في Kotlin، يمكننا تحديد الدلالات بشكل صريح.

\n\n

إضافة دور للعنصر

\n
binding.customView.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES\nbinding.customView.accessibilityDelegate = object : View.AccessibilityDelegate() {\n    override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo) {\n        super.onInitializeAccessibilityNodeInfo(host, info)\n        info.text = "القيمة الحالية: ${viewModel.value}"\n        info.contentDescription = "منزلق الصوت"\n    }\n}
\n\n

هذا الكود يخبر النظام: "مرحبًا، هذا ليس مجرد مربع، إنه منزلق!". سيفهم TalkBack أن العنصر تفاعلي وسيتمكن من التفاعل بشكل صحيح.

\n\n

تجميع العناصر

\n

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

\n\n
binding.cardProduct.apply {\n    isFocusable = true\n    contentDescription = "المنتج: ${product.name}، السعر: ${product.price} ريال"\n}
\n\n

الآن سيقرأ TalkBack جميع المعلومات بنقرة واحدة.

\n\n

التنقل بالإجراءات: لوحة المفاتيح و D-pad

\n\n

ليس كل المستخدمين يلمسون الشاشة بأصابعهم. البعض يستخدم لوحة المفاتيح (عبر OTG) أو D-pad (جهاز التحكم). يجب أن يكون تطبيقك قابلاً للتحكم دون لمس.

\n\n

في Kotlin، يتم حل ذلك من خلال focusable وترتيب التركيز (nextFocusDown، nextFocusForward).

\n\n
binding.buttonNext.nextFocusForwardId = R.id.buttonConfirm\nbinding.buttonConfirm.nextFocusDownId = R.id.buttonCancel
\n\n

تحقق من أن جميع العناصر التفاعلية تحصل على التركيز. خطأ شائع هو TextView مع ClickableSpan (رابط في النص). افتراضيًا، لا يتم التركيز عليه. نصلح ذلك:

\n\n
binding.textWithLink.movementMethod = LinkMovement                

المدونات

توصيات الكتب