VoiceOver على iOS: حل المشكلات الشائعة

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



يعد التكيف مع تطبيق iOS موضوعًا كبيرًا ، ولم يتناسب كل شيء مع مقال واحد ، لذلك أصدرهم في سلسلة.

  1. التحكم الصوتي و VoiceOver: كيفية تكييف التطبيق للمكفوفين أو الثابتين .
  2. VoiceOver على iOS: يتصرف كل عنصر تحكم بشكل مختلف.
  3. VoiceOver على iOS: حل المشكلات الشائعة.
  4. الفرق بين تنفيذ اختبارات VoiceOver والتحكم الصوتي وواجهة المستخدم. (في تقدم)

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

سنستمر اليوم في العمل على تكييف شاشة البيتزا: سنغير ترتيب الزحف ونلخص معلومات الشراء ونصلح نافذة الوسائط ونحسن مؤشر التحميل.

إعادة ترتيب عناصر التحكم


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

سيتم تمرير الشاشة والأزرار أعلاه UIScrollView. اتضح أن VoiceOver يحاول أولاً تجاوز جميع العناصر في الداخل UIScrollViewوبعد ذلك فقط يجد الأزرار العلوية. بالنسبة للمستخدم ، سيكون سلوك VoiceOver خاطئًا: الأزرار في الأعلى ، لذا يجب أن يبدأ التكرار والتسجيل بها.

للبدء ، دعنا أولاً نكتشف كيف يحدد VoiceOver ترتيب عناصر التحكم. يفعل ذلك بهذه الطريقة: يأخذ العناصر من الممتلكات accessibilityElements. بشكل افتراضي ، كلهم viewهناك isAccessibilityElement = true.

الآن يمكننا وضع الأزرار في البداية عن طريق تجاوز accessibilityElements:

override var accessibilityElements: [Any]? {
    get {
        var elements = [Any]()
            
        elements.append(contentsOf: [closeButton, cartButton])
        elements.append(contentsOf: contentScrollView.accessibilityElements)
            
        return elements
    }
    set { }
}

المجموعة من خلال shouldGroupAccessibilityChildren


عادة ، يحاول VoiceOver قراءة العناصر بترتيب طبيعي - من اليسار إلى اليمين ، من الأعلى إلى الأسفل:



إذا كنت قد قمت بتجميع عناصر التحكم ، فأنت بحاجة إلى VoiceOver للانتقال إلى أقرب عنصر في المجموعة ، وليس في ترتيب القراءة. تعيين .shouldGroupAccessibilityChildren = true، وسيبدأ الترتيب في مراعاة قرب العناصر. يجب تعيين الخاصية لتكون الأصل viewلجميع العناصر.



أشر إلى العنصر الأول للتركيز


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

ماذا تفعل Apple؟
من الغريب أن UINavigationControllerيركز على زر "رجوع" ، يمكنني وضعه على عنوان الشاشة التي تفتح. من ناحية الراحة ، يبدو لي أن من الصحيح التركيز على العنوان أو التحكم الأول ، لذلك نقدم المزيد من المعلومات حول الشاشة الجديدة. يمكنك العودة بإيماءة فرك .

يمكنك إعادة ترتيب التركيز باستخدام وظيفة التنبيه UIAccessibility.post(notification: …). يستغرق معلمتين:

  • أحد الأنواع UIAccessibility.Notification.
  • الكائن الذي يجب تطبيق التنبيه عليه. غالبًا ما يكون هذا سطرًا يحتوي على نص أو كائن يجب تحديده بعد الإشعار.

يمكنك التركيز على الرأس في viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()
        
    UIAccessibility.post(notification: .screenChanged,
                         argument: titleLabel);
}

يمكنك نقل الكائن الذي تريد التركيز عليه أو النص الذي سيتم نطقه.

أنواع التنبيهات للكائنات


  • .screenChanged — , . - .
  • .layoutChanged — . , , «» .
  • .announcement — . . , . , .

    DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
    		UIAccessibility.post(notification: .announcement,
                             argument: text)
    }
  • .pageScrolled.UIScrollView « 3 5», . , , .
  • .pauseAssistiveTechnology .resumeAssistiveTechnology —  VoiceOver.

إظهار الإطارات مشروط أصلاً


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

واجهنا أيضًا مشكلة أنه لا يمكننا تغيير المكونات بأي شكل من الأشكال ، لأنه لم يكن من الممكن التركيز على النافذة. حدث ذلك لأننا أظهرنا وجهة النظر ، وليس UIViewControllerمع UIPresentationController.VoiceOver الخاص الذي يتناوله .firstResponder، viewولم يكن لدينا .



إذا لم يكن هناك وقت لإعادة الكتابة ، فيمكنك viewتعيين الخاصية لـ accessibilityViewIsModal. ثم سوف تركز VoiceOver فقط على ذلك view.

override var accessibilityViewIsModal: Bool {
    get { return true }
    set {}
}

بصراحة ، لم يفلح لي ذلك أبدًا ، ونحن UIPresentationController.

محاذاة الإطارات غير المرئية


يتم حساب ترتيب القراءة بواسطة الإطارات ، وأحيانًا يعطي نتائج غير متوقعة. على سبيل المثال ، قمنا بتكبير إطار الزر "i" لتسهيل النقر. ولكن اتضح أنه أعلى من إطار اسم البيتزا ، لذلك تبين أن الزر "i" هو أول عنصر تركيز. على الرغم من أنها صغيرة ، إلا أنها على اليمين وهي ليست مهمة بشكل عام.



يمكنك تغيير ترتيب القراءة من خلال accessibilityElements، ولكن سأظهر بطريقة مختلفة. يستخدم VoiceOver الخاصية accessibilityFrame، بشكل افتراضي فقط يطابق الإطار المعتاد. هناك العديد من الحلول:

  1. تجاوز الفئة الفرعية للتحكم وإرجاع قيمة مخفضة.
  2. اضبط الإطار الصحيح بالخارج.
  3. فقط اضبط الإطار بحيث يكون محاطًا بالنقش.

ولكن من المهم أن يكون هذا الإطار في إحداثيات الشاشة. لتحويل بسيط هناك وظيفة UIAccessibility.convertToScreenCoordinates.

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

override func layoutSubviews() {
        super.layoutSubviews()
        repeatSwitch.accessibilityLabel = repeatLabel.text
        repeatSwitch.accessibilityFrame = UIAccessibility.convertToScreenCoordinates(
                repeatSwitch.frame.union(repeatLabel.frame).insetBy(dx: -12, dy: -12),
                in: repeatSwitch.superview!)
}

كما جعلت التركيز أكبر باستخدامه .inset، وهو أكثر ملاءمة للضغط.



باستخدام الإطار AccessibilityContainerويمكنك إتاحة الرسوم البيانية والجداول.

لخص الإجراء الرئيسي


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

على سبيل المثال ، للحصول على "زر الشراء. إضافة لحم الخنزير المقدد وإزالة الهالبينو. السعر 434₽ »، لست بحاجة لكتابة أي شيء غير عادي في الكود ، ما عليك سوى جمع السطر بإضافة / إزالة:

accessibilityTraits = .button
accessibilityLabel = ""
accessibilityValue = " ,  .  434₽" 

ولا تنس التوقيع على مؤشر التنزيل


إذا قمت بعد إضافة منتج إلى سلة التسوق بحجب الواجهة لفترة وجيزة وتنزيل شيء ما ، فلا تنس إتاحة مؤشر التنزيل:

  1. استخدم التنبيه للتركيز على المؤشر.
  2. قم بتسمية التركيز. على سبيل المثال ، تحميل.
  3. ضعها accessibilityViewIsModal.
  4. اعلمني عندما ينتهي التحميل

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

ماذا تفعل Apple؟
ومن المثير للاهتمام ، أن Safari يعمل مع هذا في نظام iOS 13: أثناء تحميل الصفحة ، فإنه يقوم بنقرة كل ثانية ، وعندما يتم تحميل الصفحة ، فإنه * woop-dumb *. للأسف ، من جانب api هذا غير متوفر حتى الآن ، نحن في انتظار iOS 14.



لتكييف الشاشة ، استخدمنا أساليب مختلفة: قمنا بتغيير ترتيب الأزرار ، وأشرنا إلى العنصر الأول للتركيز ، وقمنا بإصلاح النافذة المشروطة ، ولخصنا الإعدادات على الزر الرئيسي وعملنا على راحة التطبيق. هذه المعرفة كافية لتكييف أي تطبيق تقريبًا. إنطلق.

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

All Articles