ขั้นตอนสำคัญในการปรับปรุงการช่วยเหลือพิเศษใน Compose

ออกแบบเพื่อช่วยให้ผู้ใช้ที่ต้องการการช่วยเหลือพิเศษใช้แอปของคุณได้สำเร็จ เพื่อรองรับข้อกำหนดการช่วยเหลือพิเศษที่สำคัญ

พิจารณาขนาดเป้าหมายการสัมผัสขั้นต่ำ

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

คอมโพเนนต์เนื้อหา เช่น Checkbox, RadioButton, Switch Slider และ Surface ตั้งค่าขนาดขั้นต่ำนี้โดยใช้ภายใน เวลาที่คอมโพเนนต์สามารถรับการทำงานของผู้ใช้ เช่น เมื่อ Checkbox มี พารามิเตอร์ onCheckedChange ที่ตั้งค่าเป็นค่าที่ไม่ใช่ค่าว่าง ช่องทำเครื่องหมายจะมี ให้มีความกว้างและความสูงอย่างน้อย 48 dp

@Composable
private fun CheckableCheckbox() {
    Checkbox(checked = true, onCheckedChange = {})
}

เมื่อตั้งค่าพารามิเตอร์ onCheckedChange เป็น Null จะไม่มีการเว้นระยะห่างจากขอบ เนื่องจากไม่สามารถโต้ตอบกับคอมโพเนนต์โดยตรง

@Composable
private fun NonClickableCheckbox() {
    Checkbox(checked = true, onCheckedChange = null)
}

วันที่
รูปที่ 1 ช่องทำเครื่องหมายที่ไม่มีระยะห่างจากขอบ

เมื่อใช้การควบคุมการเลือก เช่น Switch, RadioButton หรือ Checkbox โดยปกติคุณจะยกพฤติกรรมที่สามารถคลิกได้ให้กับคอนเทนเนอร์หลัก คลิก Callback บน Composable กับ null และเพิ่ม toggleable หรือ selectable ตัวแก้ไขเป็น Composable ระดับบนสุด

@Composable
private fun CheckableRow() {
    MaterialTheme {
        var checked by remember { mutableStateOf(false) }
        Row(
            Modifier
                .toggleable(
                    value = checked,
                    role = Role.Checkbox,
                    onValueChange = { checked = !checked }
                )
                .padding(16.dp)
                .fillMaxWidth()
        ) {
            Text("Option", Modifier.weight(1f))
            Checkbox(checked = checked, onCheckedChange = null)
        }
    }
}

เมื่อขนาดของ Composable ที่สามารถคลิกได้นั้นเล็กกว่าเป้าหมายการสัมผัสขั้นต่ำ การเขียนยังจะเพิ่มขนาดเป้าหมายการสัมผัส ด้วยการขยาย ขนาดเป้าหมายการสัมผัสอยู่นอกขอบเขตของ Composable

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

@Composable
private fun SmallBox() {
    var clicked by remember { mutableStateOf(false) }
    Box(
        Modifier
            .size(100.dp)
            .background(if (clicked) Color.DarkGray else Color.LightGray)
    ) {
        Box(
            Modifier
                .align(Alignment.Center)
                .clickable { clicked = !clicked }
                .background(Color.Black)
                .size(1.dp)
        )
    }
}

เพื่อป้องกันการทับซ้อนกันระหว่างพื้นที่ที่สัมผัสของ Composable ต่างๆ โปรดทำเสมอ ใช้ขนาดขั้นต่ำที่ใหญ่พอสำหรับ Composable ในตัวอย่างนี้ หมายถึงการใช้แป้นกดร่วม sizeIn เพื่อกำหนดขนาดต่ำสุดสำหรับกล่องด้านใน:

@Composable
private fun LargeBox() {
    var clicked by remember { mutableStateOf(false) }
    Box(
        Modifier
            .size(100.dp)
            .background(if (clicked) Color.DarkGray else Color.LightGray)
    ) {
        Box(
            Modifier
                .align(Alignment.Center)
                .clickable { clicked = !clicked }
                .background(Color.Black)
                .sizeIn(minWidth = 48.dp, minHeight = 48.dp)
        )
    }
}

เพิ่มป้ายกำกับการคลิก

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

กำหนดป้ายกำกับการคลิกโดยการส่งพารามิเตอร์ในตัวแก้ไข clickable ดังนี้

@Composable
private fun ArticleListItem(openArticle: () -> Unit) {
    Row(
        Modifier.clickable(
            // R.string.action_read_article = "read article"
            onClickLabel = stringResource(R.string.action_read_article),
            onClick = openArticle
        )
    ) {
        // ..
    }
}

หรือหากคุณไม่มีสิทธิ์เข้าถึงตัวปรับแต่งที่คลิกได้ ให้ตั้งค่า ป้ายกำกับการคลิกในตัวปรับราคาเสนอความหมาย ดังนี้

@Composable
private fun LowLevelClickLabel(openArticle: () -> Boolean) {
    // R.string.action_read_article = "read article"
    val readArticleLabel = stringResource(R.string.action_read_article)
    Canvas(
        Modifier.semantics {
            onClick(label = readArticleLabel, action = openArticle)
        }
    ) {
        // ..
    }
}

อธิบายองค์ประกอบภาพ

เมื่อคุณกำหนด Composable ของ Image หรือ Icon จะไม่มี แบบอัตโนมัติเพื่อให้เฟรมเวิร์ก Android เข้าใจว่าแอปคืออะไร ปรากฏขึ้น คุณต้องส่งคำอธิบายแบบข้อความขององค์ประกอบภาพ

ลองนึกถึงหน้าจอที่ผู้ใช้สามารถแชร์หน้าเว็บปัจจุบันกับเพื่อน ช่วงเวลานี้ ที่มีไอคอนแชร์ที่คลิกได้

แถบไอคอนที่คลิกได้ โดยมีไอคอน

เฟรมเวิร์กของ Android ไม่สามารถอธิบายด้วยไอคอนเพียงอย่างเดียวได้ ผู้ใช้ที่มีความบกพร่อง เฟรมเวิร์ก Android ต้องการคำอธิบายเพิ่มเติมแบบข้อความเกี่ยวกับ ไอคอน

พารามิเตอร์ contentDescription อธิบายองค์ประกอบภาพ ใช้คำแปล ตามที่ผู้ใช้มองเห็นได้

@Composable
private fun ShareButton(onClick: () -> Unit) {
    IconButton(onClick = onClick) {
        Icon(
            imageVector = Icons.Filled.Share,
            contentDescription = stringResource(R.string.label_share)
        )
    }
}

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

@Composable
private fun PostImage(post: Post, modifier: Modifier = Modifier) {
    val image = post.imageThumb ?: painterResource(R.drawable.placeholder_1_1)

    Image(
        painter = image,
        // Specify that this image has no semantic meaning
        contentDescription = null,
        modifier = modifier
            .size(40.dp, 40.dp)
            .clip(MaterialTheme.shapes.small)
    )
}

คุณจะเป็นผู้ตัดสินใจเองว่าองค์ประกอบภาพหนึ่งๆ จำเป็นต้องมี contentDescription ถามตัวเองว่าองค์ประกอบสื่อถึงข้อมูลที่ ที่ผู้ใช้จะต้องดำเนินการ หากไม่ คุณควรออกจาก คำอธิบาย

รวมองค์ประกอบ

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

เมื่อใช้ตัวแก้ไข clickable กับ Composable การเขียน จะรวมเอลิเมนต์ทั้งหมดที่ Composable อยู่รวมกันโดยอัตโนมัติ และการทำเช่นนี้ยังมีประโยชน์สำหรับ ListItem; องค์ประกอบต่างๆ ภายในลิสต์รายการรวมกัน และความสามารถเข้าถึงได้ง่าย บริการจะดูเป็นองค์ประกอบเดียว

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

กลุ่มขององค์ประกอบ UI ที่มีชื่อผู้ใช้ เลือกชื่อแล้ว

คุณสามารถเปิดใช้การเขียนเพื่อรวมองค์ประกอบเหล่านี้โดยใช้ mergeDescendants ในตัวแก้ไข semantics วิธีนี้ทำให้บริการการช่วยเหลือพิเศษ เลือกเฉพาะองค์ประกอบที่ผสานและคุณสมบัติทางอรรถศาสตร์ทั้งหมดขององค์ประกอบสืบทอด แล้ว

@Composable
private fun PostMetadata(metadata: Metadata) {
    // Merge elements below for accessibility purposes
    Row(modifier = Modifier.semantics(mergeDescendants = true) {}) {
        Image(
            imageVector = Icons.Filled.AccountCircle,
            contentDescription = null // decorative
        )
        Column {
            Text(metadata.author.name)
            Text("${metadata.date} • ${metadata.readTimeMinutes} min read")
        }
    }
}

ตอนนี้บริการการช่วยเหลือพิเศษจะมุ่งเน้นที่คอนเทนเนอร์ทั้งหมดในคราวเดียวโดยผสานเข้าด้วยกัน เนื้อหาของพวกเขา:

กลุ่มขององค์ประกอบ UI ที่มีชื่อผู้ใช้ เลือกองค์ประกอบทั้งหมดไว้ด้วยกัน

เพิ่มการกระทำที่กำหนดเอง

ดูรายการต่อไปนี้

รายการทั่วไปที่มีชื่อบทความ ผู้เขียน และไอคอนบุ๊กมาร์ก

เมื่อคุณใช้โปรแกรมอ่านหน้าจอ เช่น TalkBack เพื่อฟังสิ่งที่แสดงบน หน้าจอจะเลือกรายการทั้งหมด จากนั้นเลือกไอคอนบุ๊กมาร์ก

รายการ โดยองค์ประกอบทั้งหมดที่เลือกไว้ด้วยกัน

รายการที่เลือกเฉพาะไอคอนบุ๊กมาร์ก

ปัญหานี้อาจใช้เวลานานเกินไป วิธีการที่ดีกว่าคือ กำหนดการกระทำแบบกำหนดเองที่อนุญาตให้ผู้ใช้ทำบุ๊กมาร์กรายการดังกล่าว โปรดทราบ คุณต้องนำลักษณะการทำงานของไอคอนบุ๊กมาร์กออก เพื่อไม่ให้เลือกโดยบริการการช่วยเหลือพิเศษ ช่วงเวลานี้ จะใช้ตัวแก้ไข clearAndSetSemantics ดังนี้

@Composable
private fun PostCardSimple(
    /* ... */
    isFavorite: Boolean,
    onToggleFavorite: () -> Boolean
) {
    val actionLabel = stringResource(
        if (isFavorite) R.string.unfavorite else R.string.favorite
    )
    Row(
        modifier = Modifier
            .clickable(onClick = { /* ... */ })
            .semantics {
                // Set any explicit semantic properties
                customActions = listOf(
                    CustomAccessibilityAction(actionLabel, onToggleFavorite)
                )
            }
    ) {
        /* ... */
        BookmarkButton(
            isBookmarked = isFavorite,
            onClick = onToggleFavorite,
            // Clear any semantics properties set on this node
            modifier = Modifier.clearAndSetSemantics { }
        )
    }
}

อธิบายสถานะขององค์ประกอบ

Composable จะกำหนด stateDescription สำหรับความหมายซึ่ง เฟรมเวิร์ก Android ใช้เพื่ออ่านสถานะของ Composable นั้น สำหรับ เช่น Composable ที่สลับได้จะอยู่ในแท็ก "เลือกไว้" หรือ "ไม่เลือก" ในบางกรณี คุณอาจต้องการลบล้างคำอธิบายสถานะเริ่มต้น ที่ Compose จะใช้ โดยระบุรัฐอย่างชัดเจน ป้ายกำกับคำอธิบายก่อนกำหนด Composable เป็นแบบเปิด/ปิดได้

@Composable
private fun TopicItem(itemTitle: String, selected: Boolean, onToggle: () -> Unit) {
    val stateSubscribed = stringResource(R.string.subscribed)
    val stateNotSubscribed = stringResource(R.string.not_subscribed)
    Row(
        modifier = Modifier
            .semantics {
                // Set any explicit semantic properties
                stateDescription = if (selected) stateSubscribed else stateNotSubscribed
            }
            .toggleable(
                value = selected,
                onValueChange = { onToggle() }
            )
    ) {
        /* ... */
    }
}

กำหนดส่วนหัว

บางครั้งแอปจะแสดงเนื้อหาจำนวนมากในหน้าจอเดียวในคอนเทนเนอร์ที่เลื่อนได้ ตัวอย่างเช่น หน้าจอสามารถแสดงเนื้อหาทั้งหมดของบทความที่ผู้ใช้ กำลังอ่าน:

ภาพหน้าจอของบล็อกโพสต์ที่มีข้อความของบทความในคอนเทนเนอร์ที่เลื่อนได้

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

ในการเขียน คุณจะระบุว่า Composable เป็นส่วนหัวโดยการกำหนด พร็อพเพอร์ตี้ semantics:

@Composable
private fun Subsection(text: String) {
    Text(
        text = text,
        style = MaterialTheme.typography.headlineSmall,
        modifier = Modifier.semantics { heading() }
    )
}

จัดการ Composable ที่กำหนดเอง

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

สมมติว่าคุณกำลังแทนที่ Material Checkbox ด้วยการติดตั้งใช้งานของคุณเอง คุณอาจลืมเพิ่มตัวแก้ไข triStateToggleable ซึ่งแฮนเดิล คุณสมบัติการช่วยเหลือพิเศษของคอมโพเนนต์นี้

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

ทดสอบการใช้งานคอมโพเนนต์ที่กำหนดเองกับ บริการการช่วยเหลือพิเศษเพื่อยืนยันลักษณะการทำงานของบริการ

แหล่งข้อมูลเพิ่มเติม