Focus Order — คืออะไร หลักการ และวิธีกำหนดค่าในแอปพลิเคชันมือถือ

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-05-16 เวลาอ่าน: 9 นาที

Focus Order คือลำดับที่องค์ประกอบอินเทอร์เฟสได้รับโฟกัสเมื่อนำทางด้วยแป้นพิมพ์ Switch Control VoiceOver หรือ TalkBack ในแอปพลิเคชันมือถือ ลำดับโฟกัสจะกำหนดว่าผู้ใช้เคลื่อนที่ระหว่างตัวควบคุมด้วยท่าทางหรือปุ่มต่างๆ อย่างไร ตาม W3C WCAG 2.2, Success Criterion 2.4.3, 2023 โฟกัสต้องเป็นไปตามลำดับตรรกะที่รักษาความหมายของเนื้อหา การละเมิดหลักการนี้เป็นหนึ่งในสาเหตุทั่วไปของ ความล้มเหลว ในการตรวจสอบการเข้าถึง

ประเด็นสำคัญ

  • Focus Order — ลำดับการเดินผ่านองค์ประกอบแบบโต้ตอบเมื่อนำทางด้วยแป้นพิมพ์หรือโปรแกรมอ่านหน้าจอ
  • โฟกัสต้องเป็นไปตาม ลำดับภาพ (ซ้ายไปขวา บนลงล่าง) และรักษาตรรกะของเนื้อหา
  • ใน iOS ลำดับถูกควบคุมผ่าน shouldGroupAccessibilityElement และอาร์เรย์ accessibilityElements
  • ใน Android แอตทริบิวต์ nextFocusDown nextFocusUp nextFocusLeft nextFocusRight กำหนดเพื่อนบ้านโฟกัส
  • หน้าจอแบบกำหนดเอง (แผนที่ แคนวาส เกม) ต้องการ การจัดการโฟกัสเชิงโปรแกรม ผ่าน UIAccessibilityPostNotification

Focus Order ในการเข้าถึงคืออะไร

Focus Order คือลำดับที่ผู้ใช้เคลื่อนที่ระหว่างองค์ประกอบแบบโต้ตอบด้วยวิธีการป้อนข้อมูลทางเลือก: แป้นพิมพ์ (Tab), Switch Control (ทีละขั้น), VoiceOver (ปัดขวา/ซ้าย) หรือ TalkBack แตกต่างจากเมาส์หรือหน้าจอสัมผัสที่ผู้ใช้เลือกองค์ประกอบโดยตรง การนำทางด้วยโฟกัสเป็นแบบเส้นตรง — แต่ละขั้นจะย้ายโฟกัสไปยังองค์ประกอบถัดไป

ตาม Apple HIG, 2024 VoiceOver ใช้ลำดับขององค์ประกอบในแผนผังการเข้าถึง ซึ่งสร้างขึ้นตามตำแหน่งภาพ: มุมซ้ายบน → มุมขวาล่าง หากหน้าจอมีเค้าโครงที่ซับซ้อน (คอลัมน์ Grid ZStack) แผนผังอาจไม่ตรงกับลำดับภาพ

หลักการ WCAG 2.4.3: “หากหน้าเว็บสามารถ นำทางตามลำดับ ผ่านส่วนต่างๆ และลำดับโฟกัสส่งผลต่อความหมาย โฟกัสต้องเป็นไปตามลำดับที่รักษาความหมายและความสามารถในการใช้งาน” ข้อยกเว้น: เนื้อหาแบบไดนามิกที่โฟกัสสามารถกระโดดเพื่อดึงดูดความสนใจ (การแจ้งเตือน หน้าต่างโมดอล)

ทำไม Focus Order จึงสำคัญสำหรับการเข้าถึง

ผู้ใช้ Switch Control (ผู้ที่มีความบกพร่องทางการเคลื่อนไหว) เคลื่อนที่ผ่านองค์ประกอบโดยอัตโนมัติ — รอบแล้วรอบเล่า หากลำดับเสียหาย ผู้ใช้ใช้เวลาในการกรอกแบบฟอร์มมากกว่า 3 เท่า ตาม Deque University, 2024 Focus Order ที่ถูกต้องจะลดเวลาในการกรอกแบบฟอร์มลง 60% สำหรับผู้ใช้เทคโนโลยีช่วยเหลือ

Focus Order และหน้าต่างโมดอล

ให้ความสนใจเป็นพิเศษ — หน้าต่างโมดอล หลังจากเปิดโมดอล โฟกัสต้อง ย้ายทันที ไปยังองค์ประกอบแบบโต้ตอบแรกภายในโมดอล (โดยปกติคือปุ่ม “ปิด” หรือ “ยืนยัน”) หลังจากปิด — กลับไปยังองค์ประกอบที่เรียกโมดอล นี่คือข้อกำหนดของ WCAG 2.4.3 และเป็นข้อผิดพลาดทั่วไปด้วย

iOS: การจัดการลำดับโฟกัส

ใน iOS VoiceOver จะสร้างลำดับโดยอัตโนมัติตามเรขาคณิต: องค์ประกอบจะถูกจัดเรียงตาม Y จากนั้นตาม X สำหรับหน้าจอที่มีโครงสร้างซับซ้อน ลำดับนี้อาจไม่ถูกต้อง — นักพัฒนาต้องเข้ามาแทรกแซง

เครื่องมือหลัก:

  • shouldGroupAccessibilityElement — จัดกลุ่มองค์ประกอบย่อยเป็นบล็อกตรรกะเดียว
  • accessibilityElements — อาร์เรย์ที่กำหนดลำดับแบบกำหนดเองขององค์ประกอบย่อย
  • UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, element) — การย้ายโฟกัสเชิงโปรแกรม

ตัวอย่างการตั้งค่าลำดับแบบกำหนดเองสำหรับบัตรสินค้า:

swift
class ProductCardView: UIView {
    let titleLabel = UILabel()
    let priceLabel = UILabel()
    let buyButton = UIButton()

    override var accessibilityElements: [Any]? {
        get {
            return [titleLabel!, priceLabel!, buyButton!]
        }
        set {}
    }
}

สำหรับการย้ายโฟกัสเชิงโปรแกรมหลังการดำเนินการ:

swift
UIAccessibility.post(
    notification: .layoutChanged,
    argument: newlyAddedItem
)

shouldGroupAccessibilityElement ในทางปฏิบัติ

คุณสมบัติ shouldGroupAccessibilityElement มีประโยชน์สำหรับบัตรในคอลเล็กชัน หากตั้งค่าเป็น true ที่บัตรหลัก VoiceOver จะรับรู้ทั้งบัตรเป็นองค์ประกอบเดียว ผู้ใช้สามารถแตะสองครั้งเพื่อเปิดใช้งานทั้งบัตร หรือกำหนดค่าโรเตอร์สำหรับการนำทางภายใน แนะนำสำหรับ UICollectionViewCell และ UITableViewCell

Android: แอตทริบิวต์ทิศทางโฟกัส

ใน Android TalkBack ก็ใช้ลำดับเรขาคณิตเช่นกัน แต่ให้ความสำคัญกับแอตทริบิวต์ nextFocus* ที่ชัดเจน แอตทริบิวต์เหล่านี้ถูกกำหนดใน XML หรือเชิงโปรแกรม:

แอตทริบิวต์วัตถุประสงค์ตัวอย่าง
nextFocusDownองค์ประกอบเมื่อนำทางลง@+id/field_email
nextFocusUpองค์ประกอบเมื่อนำทางขึ้น@+id/field_name
nextFocusLeftองค์ประกอบทางซ้าย@+id/btn_back
nextFocusRightองค์ประกอบทางขวา@+id/btn_next

ตัวอย่างสำหรับแบบฟอร์มลงทะเบียน:

xml
<EditText
    android:id="@+id/field_email"
    android:nextFocusDown="@+id/field_password" />

<EditText
    android:id="@+id/field_password"
    android:nextFocusDown="@+id/btn_submit" />

สำหรับ RecyclerView ลำดับโฟกัสเป็นแบบไดนามิก — กำหนดโดยอะแดปเตอร์ หากเซลล์มีโครงสร้างซับซ้อน ให้ตั้งค่า descendantFocusability = “beforeDescendants” และกำหนดลำดับในโหนดรายการ สำหรับ Jetpack Compose ลำดับโฟกัสถูกกำหนดผ่าน Modifier.focusOrder() และ FocusOrder ลำดับความสำคัญ: previous (ย่อย), next (ถัดไป), คีย์แบบกำหนดเอง

TouchDelegate พื้นที่สัมผัส และพื้นที่โฟกัส

หากองค์ประกอบเล็กเกินไปสำหรับโฟกัส (น้อยกว่า 44pt) ให้เพิ่มพื้นที่สัมผัสผ่าน TouchDelegate ใน iOS หรือ minWidth/minHeight ใน Android ตาม Google Material Design, 2024 พื้นที่สัมผัสขั้นต่ำคือ 48×48dp VoiceOver และ TalkBack โฟกัสที่กล่องขอบเขตขององค์ประกอบ องค์ประกอบที่เล็กกว่า 30pt อาจไม่สามารถเข้าถึงโฟกัสด้วยท่าทาง — ผู้ใช้ไม่สามารถแตะองค์ประกอบเหล่านั้นได้ทางกายภาพ

การละเมิด WCAG 2.4.3 ทั่วไป

โฟกัสกระโดด — เมื่อหลังจากการดำเนินการ (เช่น การลบองค์ประกอบ) โฟกัสย้ายไปยังจุดเริ่มต้นของรายการหรือปุ่ม “กลับ” ของระบบ ผู้ใช้ VoiceOver สูญเสียบริบท วิธีแก้ไข: ย้ายโฟกัสเชิงโปรแกรมไปยังองค์ประกอบที่ใกล้กับองค์ประกอบที่ถูกลบมากที่สุด

โฟกัสมองไม่เห็น — องค์ประกอบได้รับโฟกัสแต่ไม่มีตัวบ่งชี้ภาพ (ผู้ใช้แป้นพิมพ์ไม่เห็นว่าพวกเขาอยู่ที่ไหน) ใน iOS ให้ตรวจสอบ UIAccessibility.isVoiceOverRunning สำหรับตัวบ่งชี้แบบกำหนดเอง ตาม Deque University, 2024 โฟกัสมองไม่เห็นเป็นสาเหตุทั่วไปอันดับสองของความล้มเหลวในการตรวจสอบการเข้าถึง

โมดอล — โฟกัสยังคงอยู่บนเนื้อหาพื้นหลังหลังจากเปิดโมดอล ใน iOS มุมมองโมดอลจะจับโฟกัสโดยอัตโนมัติหากตั้งค่า modalPresentationStyle = .pageSheet ใน Android ให้ใช้ setFocusable(true) บนคอนเทนเนอร์ไดอะล็อก

กับดักโฟกัส

ปัญหาย้อนกลับ: โฟกัสติดอยู่ภายในโมดอลและไม่สามารถออกไปได้ (ยกเว้นการปิด) สิ่งนี้ยอมรับได้ เฉพาะ สำหรับหน้าต่างโมดอล — ผู้ใช้ต้องปิดหน้าต่างโดยเจตนา สำหรับหน้าจอปกติ กับดักโฟกัสเป็นข้อผิดพลาดร้ายแรง วิธีแก้ไข: ตรวจสอบให้แน่ใจว่าองค์ประกอบสุดท้ายของโมดอล (ปุ่ม “ปิด”) ส่งโฟกัสกลับ

หน้าจอแบบกำหนดเองและโฟกัสเชิงโปรแกรม

สำหรับ หน้าจอแบบกำหนดเอง (แผนที่ แคนวาส เกม) ลำดับเรขาคณิตอัตโนมัติไม่สามารถใช้ได้ นักพัฒนาต้องสร้างแผนผังการเข้าถึงด้วยตนเอง ใน iOS เมธอด UIAccessibilityContainer ถูกแทนที่เพื่อการนี้

ตัวอย่างสำหรับแคนวาสแบบกำหนดเอง:

swift
class CanvasView: UIView {
    var shapes: [ShapeView] = []

    override var accessibilityElements: [Any]? {
        get {
            // จัดเรียงรูปร่างตาม Z-index ไม่ใช่ตามเรขาคณิต
            return shapes.sorted { $0.zIndex < $1.zIndex }
        }
        set {}
    }
}

ใน Android สำหรับ View แบบกำหนดเอง ให้แทนที่ onInitializeAccessibilityNodeInfo:

kotlin
override fun onInitializeAccessibilityNodeInfo(
    info: AccessibilityNodeInfo
) {
    super.onInitializeAccessibilityNodeInfo(info)
    info.addChild(firstElement)
    info.addChild(secondElement)
    info.isFocusable = true
}

สำหรับ รายการแบบไดนามิก (แชท ฟีดข่าว) หลังจากเพิ่มองค์ประกอบ ให้ย้ายโฟกัสไปยังองค์ประกอบใหม่แรก ใน iOS: UIAccessibility.post(notification: .layoutChanged, argument: newMessage) ใน Android: sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)

AccessibilityFrame และเรขาคณิตโฟกัส

iOS กำหนดพื้นที่โฟกัสโดยอัตโนมัติตามเฟรมขององค์ประกอบ หากองค์ประกอบมีการแปลง (transform, rotation) VoiceOver อาจโฟกัสที่พื้นที่ผิด กำหนด accessibilityFrame อย่างชัดเจนในพิกัดหน้าจอ: element.accessibilityFrame = UIAccessibility.convertToScreenCoordinates(element.bounds, in: element) สิ่งนี้ทำให้แน่ใจว่า VoiceOver เน้นพื้นที่ที่ถูกต้อง

UIKit Dynamics และการเข้าถึง

สำหรับหน้าจอเคลื่อนไหว (UIKit Dynamics, Lottie, SpriteKit) โฟกัสเชิงโปรแกรมมีความสำคัญเป็นพิเศษ VoiceOver ไม่สามารถสร้างแผนผังการเข้าถึงสำหรับองค์ประกอบที่เคลื่อนที่แบบไดนามิก ตั้งค่า isAccessibilityElement = false บนคอนเทนเนอร์แอนิเมชันและ true เฉพาะบนองค์ประกอบแบบโต้ตอบภายใน

การทดสอบลำดับโฟกัส

การทดสอบด้วยตนเอง: เปิด VoiceOver (iOS) หรือ TalkBack (Android) ปัดไปทางขวาผ่านลำดับทั้งหมด โฟกัสต้องเป็นไปตามลำดับภาพ — ซ้ายไปขวา บนลงล่าง แต่ละองค์ประกอบแบบโต้ตอบต้องได้รับโฟกัสเพียงครั้งเดียว

การทดสอบอัตโนมัติ เป็นสิ่งที่ท้าทายแต่เป็นไปได้:

swift
func testKeyboardFocusOrder() {
    let app = XCUIApplication()
    app.launch()
    app.textFields["Email"].tap()
    // Tab — เฉพาะกับแป้นพิมพ์ฮาร์ดแวร์
}

สำหรับ Android ให้ใช้ Accessibility Testing Framework:

kotlin
@Test
fun testFocusOrder() {
    onView(withId(R.id.fieldEmail))
        .check(matches(isFocusable()))
    onView(withId(R.id.fieldEmail))
        .perform(focus())
    onView(withId(R.id.fieldPassword))
        .check(matches(isFocused()))
}

วิธีที่เชื่อถือได้มากที่สุดคือ การทดสอบสถานการณ์ UI: กรอกแบบฟอร์มทีละขั้นตอน (อีเมล → รหัสผ่าน → ส่ง) ตรวจสอบว่าแต่ละขั้นตอนเสร็จสมบูรณ์ หากลำดับโฟกัสเสียหาย สถานการณ์จะล้มเหลวเมื่อพยายามโต้ตอบกับองค์ประกอบนอกโฟกัส

Xcode Accessibility Inspector สำหรับการดีบัก

เครื่องมือ Accessibility Inspector ใน Xcode แสดงแผนผังการเข้าถึงทั้งหมด คุณสามารถเดินผ่านองค์ประกอบตามลำดับ VoiceOver และดูเส้นทางโฟกัสที่แน่นอน ใช้แท็บ “Audit” สำหรับการตรวจจับการละเมิด Focus Order โดยอัตโนมัติ

คำถามที่พบบ่อย

WCAG 2.4.3 คืออะไรและข้อกำหนดเกี่ยวกับโฟกัสมีอะไรบ้าง?

WCAG 2.4.3 (Focus Order) เป็นเกณฑ์ความสำเร็จระดับ A กำหนดให้ ลำดับโฟกัส รักษาความหมายของเนื้อหาระหว่างการนำทางตามลำดับ การละเมิดถือว่าร้ายแรงและขัดขวางการรับรอง

วิธีกำหนดลำดับโฟกัสสำหรับองค์ประกอบที่ซ่อนอยู่หลังแอนิเมชัน?

องค์ประกอบที่ซ่อนต้องมี isAccessibilityElement = false ใน iOS หรือ visibility = gone/invisible ใน Android เมื่อปรากฏ ให้ย้ายโฟกัสเชิงโปรแกรมผ่าน UIAccessibility.post(notification: .layoutChanged)

โฟกัสใน iOS แตกต่างจาก Android อย่างไร?

iOS จัดการผ่าน accessibilityElements และ shouldGroupAccessibilityElement, Android จัดการผ่านแอตทริบิวต์ nextFocus* และ AccessibilityNodeInfo หลักการเหมือนกัน: ลำดับเรขาคณิตโดยค่าเริ่มต้นที่สามารถแทนที่ได้

จะทำอย่างไรถ้า RecyclerView มีลำดับผิด?

ตั้งค่า descendantFocusability = “beforeDescendants” บนองค์ประกอบรากและกำหนดค่าในอะแดปเตอร์ผ่าน onInitializeAccessibilityNodeInfo สำหรับแต่ละเซลล์

วิธีทดสอบโฟกัสโดยไม่ใช้ VoiceOver?

เชื่อมต่อ แป้นพิมพ์ฮาร์ดแวร์ ผ่าน Bluetooth หรือ USB บน iOS กด Tab เพื่อย้ายโฟกัส บน Android เปิด TalkBack และใช้ปุ่ม Tab และปุ่มลูกศร

สรุป

  • Focus Order — ลำดับการเดินผ่านองค์ประกอบเมื่อนำทางด้วยแป้นพิมพ์หรือโปรแกรมอ่านหน้าจอ; อิงตาม WCAG 2.4.3
  • โฟกัสต้องเป็นไปตาม ลำดับภาพ (ซ้ายไปขวา บนลงล่าง) — โดยอัตโนมัติใน VoiceOver และ TalkBack
  • ใน iOS ลำดับถูกควบคุมผ่าน accessibilityElements และ shouldGroupAccessibilityElement
  • ใน Android ใช้แอตทริบิวต์ nextFocusDown nextFocusUp nextFocusLeft nextFocusRight
  • หน้าจอแบบกำหนดเอง (แผนที่ แคนวาส) ต้องการ การจัดการโฟกัสเชิงโปรแกรม ผ่าน UIAccessibilityPostNotification
  • การละเมิดลำดับเป็น ข้อผิดพลาดร้ายแรง ใน WCAG 2.4.3; ผู้ใช้สูญเสียบริบทและไม่สามารถทำสถานการณ์ให้เสร็จสมบูรณ์
  • ทดสอบโฟกัสผ่านท่าทาง VoiceOver/TalkBack แป้นพิมพ์ฮาร์ดแวร์ และ สถานการณ์อัตโนมัติ

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม