แก้ไขลําดับการส่งผ่าน

ลำดับการส่งผ่านคือลําดับที่บริการการช่วยเหลือพิเศษไปยังองค์ประกอบ UI ในแอปเขียน องค์ประกอบจะจัดเรียงตามลำดับการอ่านที่คาดไว้ ซึ่งโดยทั่วไปคือจากซ้ายไปขวา แล้วจากบนลงล่าง อย่างไรก็ตาม ในบางสถานการณ์ เครื่องมือเขียนอาจต้องการคำแนะนำเพิ่มเติมเพื่อระบุลำดับการอ่านที่ถูกต้อง

isTraversalGroup และ traversalIndex เป็นพร็อพเพอร์ตี้เชิงความหมายที่ช่วยให้คุณกำหนดลำดับการเรียกดูบริการการช่วยเหลือพิเศษได้ในสถานการณ์ที่อัลกอริทึมการจัดเรียงเริ่มต้นของ Compose ไม่เพียงพอ isTraversalGroup ระบุกลุ่มที่สําคัญทางความหมายซึ่งจําเป็นต้องมีการปรับแต่ง ขณะที่ traversalIndexปรับลําดับขององค์ประกอบแต่ละรายการภายในกลุ่มเหล่านั้น คุณสามารถใช้ isTraversalGroup เพียงอย่างเดียวเพื่อระบุว่าควรเลือกองค์ประกอบทั้งหมดภายในกลุ่มพร้อมกัน หรือใช้ร่วมกับ traversalIndex เพื่อปรับแต่งเพิ่มเติมก็ได้

ใช้ isTraversalGroup และ traversalIndex ในแอปเพื่อควบคุมลำดับการไปยังส่วนต่างๆ ของโปรแกรมอ่านหน้าจอ

จัดกลุ่มองค์ประกอบสำหรับการเรียกดู

isTraversalGroup เป็นพร็อพเพอร์ตี้บูลีนที่กําหนดว่าโหนด semantics เป็นกลุ่มการทํางานแบบวนหรือไม่ โหนดประเภทนี้มีฟังก์ชันเป็นขอบเขตหรือเส้นแบ่งในการจัดระเบียบโหนดย่อย

การตั้งค่า isTraversalGroup = true ในโหนดหมายความว่าระบบจะเข้าชมองค์ประกอบย่อยทั้งหมดของโหนดนั้นก่อนที่จะไปยังองค์ประกอบอื่นๆ คุณสามารถตั้งค่า isTraversalGroup ในโหนดที่โฟกัสได้ซึ่งไม่ใช่โปรแกรมอ่านหน้าจอ เช่น คอลัมน์ แถว หรือกล่อง

ตัวอย่างต่อไปนี้ใช้ isTraversalGroup ซึ่งจะแสดงองค์ประกอบข้อความ 4 รายการ องค์ประกอบ 2 รายการทางด้านซ้ายเป็นขององค์ประกอบ CardBox รายการหนึ่ง ส่วนองค์ประกอบ 2 รายการทางด้านขวาเป็นขององค์ประกอบ CardBox รายการอื่น

// CardBox() function takes in top and bottom sample text.
@Composable
fun CardBox(
    topSampleText: String,
    bottomSampleText: String,
    modifier: Modifier = Modifier
) {
    Box(modifier) {
        Column {
            Text(topSampleText)
            Text(bottomSampleText)
        }
    }
}

@Composable
fun TraversalGroupDemo() {
    val topSampleText1 = "This sentence is in "
    val bottomSampleText1 = "the left column."
    val topSampleText2 = "This sentence is "
    val bottomSampleText2 = "on the right."
    Row {
        CardBox(
            topSampleText1,
            bottomSampleText1
        )
        CardBox(
            topSampleText2,
            bottomSampleText2
        )
    }
}

โค้ดจะแสดงผลลัพธ์ที่คล้ายกับตัวอย่างต่อไปนี้

เลย์เอาต์ที่มีข้อความ 2 คอลัมน์ โดยคอลัมน์ด้านซ้ายระบุว่า "ประโยคนี้อยู่ในคอลัมน์ด้านซ้าย" และคอลัมน์ด้านขวาระบุว่า "ประโยคนี้อยู่ทางด้านขวา"
รูปที่ 1 เลย์เอาต์ที่มี 2 ประโยค (1 ประโยคในคอลัมน์ด้านซ้ายและอีก 1 ประโยคในคอลัมน์ด้านขวา)

เนื่องจากไม่มีการตั้งค่าความหมาย ลักษณะการทํางานเริ่มต้นของโปรแกรมอ่านหน้าจอจึงเป็นการไปยังองค์ประกอบต่างๆ จากซ้ายไปขวาและจากบนลงล่าง ด้วยเหตุนี้ TalkBack จึงอ่านข้อความที่ตัดตอนมาตามลำดับที่ไม่ถูกต้องโดยค่าเริ่มต้น

"This sentence is in" → "This sentence is" → "the left column." → "ทางด้านขวา"

หากต้องการจัดเรียงข้อมูลโค้ดให้ถูกต้อง ให้แก้ไขข้อมูลโค้ดต้นฉบับเพื่อตั้งค่า isTraversalGroup เป็น true

@Composable
fun TraversalGroupDemo2() {
    val topSampleText1 = "This sentence is in "
    val bottomSampleText1 = "the left column."
    val topSampleText2 = "This sentence is"
    val bottomSampleText2 = "on the right."
    Row {
        CardBox(
//      1,
            topSampleText1,
            bottomSampleText1,
            Modifier.semantics { isTraversalGroup = true }
        )
        CardBox(
//      2,
            topSampleText2,
            bottomSampleText2,
            Modifier.semantics { isTraversalGroup = true }
        )
    }
}

เนื่องจากมีการตั้งค่า isTraversalGroup ใน CardBox แต่ละรายการโดยเฉพาะ ขอบเขต CardBox จึงมีผลเมื่อจัดเรียงองค์ประกอบ ในกรณีนี้ ระบบจะอ่าน CardBox ซ้ายก่อน ตามด้วย CardBox ขวา

ตอนนี้ TalkBack จะอ่านข้อความที่ตัดตอนมาตามลำดับที่ถูกต้อง

"ประโยคนี้อยู่ใน" → "คอลัมน์ด้านซ้าย" → "This sentence is" → "on the right."

ปรับแต่งลําดับการเรียกดู

traversalIndex เป็นพร็อพเพอร์ตี้ประเภทลอยตัวที่ช่วยให้คุณปรับแต่งลําดับการเรียกดูของ TalkBack ได้ หากการจัดกลุ่มองค์ประกอบเข้าด้วยกันไม่เพียงพอที่จะทำให้ TalkBack ทํางานได้อย่างถูกต้อง ให้ใช้ traversalIndex ร่วมกับ isTraversalGroup เพื่อปรับแต่งลําดับของโปรแกรมอ่านหน้าจอเพิ่มเติม

พร็อพเพอร์ตี้ traversalIndex มีลักษณะดังนี้

  • ระบบจะจัดลําดับความสําคัญขององค์ประกอบที่มีค่า traversalIndex ต่ำกว่าก่อน
  • อาจเป็นค่าบวกหรือค่าลบก็ได้
  • ค่าเริ่มต้นคือ 0f
  • หากต้องการให้ดัชนีการวนมีผลต่อลักษณะการวน คุณต้องตั้งค่าดัชนีนี้ในคอมโพเนนต์ที่บริการการช่วยเหลือพิเศษจะเลือกและโฟกัสได้ เช่น องค์ประกอบบนหน้าจอ เช่น ข้อความหรือปุ่ม
    • การตั้งค่า traversalIndex เพียงอย่างเดียว เช่น Column จะไม่มีผล เว้นแต่ว่าคอลัมน์จะมีการตั้งค่า isTraversalGroup ด้วย

ตัวอย่างต่อไปนี้แสดงวิธีใช้ traversalIndex และ isTraversalGroup ร่วมกัน

หน้าปัดนาฬิกาเป็นสถานการณ์ทั่วไปที่การจัดลําดับการเรียกดูมาตรฐานใช้งานไม่ได้ ตัวอย่างในส่วนนี้คือเครื่องมือเลือกเวลา ซึ่งผู้ใช้สามารถเลื่อนดูตัวเลขบนหน้าปัดนาฬิกาและเลือกตัวเลขสำหรับช่องชั่วโมงและนาที

หน้าปัดนาฬิกาที่มีเครื่องมือเลือกเวลาอยู่ด้านบน
รูปที่ 2 รูปภาพหน้าปัดนาฬิกา

ในข้อมูลโค้ดที่เขียนให้เข้าใจง่ายต่อไปนี้ มี CircularLayout ที่วาดตัวเลข 12 ตัว โดยเริ่มจาก 12 และวนตามเข็มนาฬิการอบวงกลม

@Composable
fun ClockFaceDemo() {
    CircularLayout {
        repeat(12) { hour ->
            ClockText(hour)
        }
    }
}

@Composable
private fun ClockText(value: Int) {
    Box(modifier = Modifier) {
        Text((if (value == 0) 12 else value).toString())
    }
}

เนื่องจากหน้าปัดไม่ได้อ่านอย่างมีเหตุผลตามลําดับจากซ้ายไปขวาและจากบนลงล่างที่เป็นค่าเริ่มต้น TalkBack จึงอ่านตัวเลขไม่เป็นลําดับ หากต้องการแก้ไขข้อผิดพลาดนี้ ให้ใช้ค่าตัวนับที่เพิ่มขึ้น ดังที่แสดงในข้อมูลโค้ดต่อไปนี้

@Composable
fun ClockFaceDemo() {
    CircularLayout(Modifier.semantics { isTraversalGroup = true }) {
        repeat(12) { hour ->
            ClockText(hour)
        }
    }
}

@Composable
private fun ClockText(value: Int) {
    Box(modifier = Modifier.semantics { this.traversalIndex = value.toFloat() }) {
        Text((if (value == 0) 12 else value).toString())
    }
}

หากต้องการตั้งค่าลําดับการเรียกใช้อย่างถูกต้อง ให้สร้าง CircularLayout เป็นกลุ่มการเรียกใช้ แล้วตั้งค่า isTraversalGroup = true จากนั้นเมื่อวาดข้อความนาฬิกาแต่ละรายการลงในเลย์เอาต์ ให้ตั้งค่า traversalIndex ที่สอดคล้องกันเป็นค่าตัวนับ

เนื่องจากค่าตัวนับเพิ่มขึ้นอย่างต่อเนื่อง traversalIndex ของค่านาฬิกาแต่ละค่าจึงมีขนาดใหญ่ขึ้นเมื่อมีการใส่ตัวเลขลงในหน้าจอ ค่านาฬิกา 0 มี traversalIndex เป็น 0 และค่านาฬิกา 1 มี traversalIndex เป็น 1 วิธีนี้เป็นการกําหนดลําดับที่ TalkBack จะอ่าน ตอนนี้ ระบบจะอ่านตัวเลขภายใน CircularLayout ตามลำดับที่คาดไว้

เนื่องจาก traversalIndexes ที่ตั้งไว้จะสัมพันธ์กับดัชนีอื่นๆ ภายในการจัดกลุ่มเดียวกันเท่านั้น ระบบจึงยังคงการจัดเรียงหน้าจอที่เหลือไว้ กล่าวคือ การเปลี่ยนแปลงเชิงความหมายที่แสดงในข้อมูลโค้ดก่อนหน้าจะแก้ไขเฉพาะลําดับภายในหน้าปัดที่ตั้งค่าisTraversalGroup = trueเท่านั้น

โปรดทราบว่าหากไม่ได้ตั้งค่าความหมายของ CircularLayout's เป็น isTraversalGroup = true การเปลี่ยนแปลง traversalIndex จะยังคงมีผล อย่างไรก็ตาม หากไม่มี CircularLayout เพื่อเชื่อมโยง ตัวเลข 12 หลักของหน้าปัดนาฬิกาจะอ่านเป็นลำดับสุดท้ายหลังจากที่ระบบอ่านองค์ประกอบอื่นๆ ทั้งหมดบนหน้าจอแล้ว ปัญหานี้เกิดขึ้นเนื่องจากองค์ประกอบอื่นๆ ทั้งหมดมี traversalIndex เริ่มต้นเป็น 0f และระบบจะอ่านองค์ประกอบข้อความนาฬิกาหลังจากองค์ประกอบ 0f อื่นๆ ทั้งหมด

ข้อควรพิจารณาเกี่ยวกับ API

โปรดคำนึงถึงสิ่งต่อไปนี้เมื่อใช้ Traversal API

  • ควรตั้งค่า isTraversalGroup = true ในองค์ประกอบหลักที่มีองค์ประกอบที่จัดกลุ่ม
  • traversalIndex ควรตั้งค่าในคอมโพเนนต์ย่อยที่มีความหมาย และบริการการช่วยเหลือพิเศษจะเป็นผู้เลือก
  • ตรวจสอบว่าองค์ประกอบทั้งหมดที่คุณกําลังตรวจสอบอยู่ในระดับzIndex เดียวกัน เนื่องจากระดับดังกล่าวจะส่งผลต่อความหมายและลําดับการเรียกดูด้วย
  • ตรวจสอบว่าไม่มีการผสานความหมายโดยไม่จำเป็น เนื่องจากอาจส่งผลต่อดัชนีการเรียกดูองค์ประกอบที่จะใช้