ค่าเริ่มต้นของ API

Material, Compose UI และ Foundation API ใช้และนำเสนอแนวทางปฏิบัติที่เข้าถึงได้ง่ายหลายอย่างโดยค่าเริ่มต้น องค์ประกอบเหล่านี้มีความหมายในตัวซึ่งเป็นไปตามบทบาทและฟังก์ชันที่เฉพาะเจาะจง ซึ่งหมายความว่าจะมีการสนับสนุนการช่วยเหลือพิเศษส่วนใหญ่โดยแทบไม่ต้องดำเนินการใดๆ เพิ่มเติม

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

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

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

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

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

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

ช่องทําเครื่องหมายที่มีระยะห่างจากขอบเริ่มต้นที่มีความกว้างและความสูง 48 dp
รูปที่ 1 ช่องทำเครื่องหมายที่มีระยะห่างจากขอบเริ่มต้น

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

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

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

เมื่อใช้ตัวควบคุมการเลือก เช่น Switch, RadioButton หรือ Checkbox โดยทั่วไปคุณจะต้องยกระดับลักษณะการคลิกไปยังคอนเทนเนอร์หลักโดยการตั้งค่าการเรียกกลับการคลิกใน 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)
        }
    }
}

ช่องทำเครื่องหมายข้างข้อความ "ตัวเลือก" ที่เลือกและยกเลิกการเลือก
รูปที่ 3 ช่องทําเครื่องหมายที่คลิกได้

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

ตัวอย่างต่อไปนี้มี 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)
        )
    }
}

ช่องขนาดเล็กมากที่คลิกได้ซึ่งจะขยายเป็นเป้าหมายการสัมผัสที่ใหญ่ขึ้นโดยการแตะข้างช่อง
รูปที่ 4 กล่องขนาดเล็กมากที่คลิกได้ซึ่งจะขยายเป็นเป้าหมายการสัมผัสขนาดใหญ่

โปรดใช้ขนาดขั้นต่ำที่ใหญ่พอสำหรับคอมโพสิเบิลเสมอ เพื่อป้องกันไม่ให้พื้นที่สัมผัสของคอมโพสิเบิลต่างๆ ทับซ้อนกัน ในตัวอย่างนี้ หมายความว่าจะใช้ตัวปรับ 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)
        )
    }
}

กล่องขนาดเล็กมากจากตัวอย่างก่อนหน้ามีขนาดใหญ่ขึ้นเพื่อสร้างเป้าหมายการสัมผัสที่ใหญ่ขึ้น
รูปที่ 5 เป้าหมายการสัมผัสกล่องขนาดใหญ่ขึ้น

องค์ประกอบกราฟิก

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

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

แถบไอคอน 4 รายการที่คลิกได้ โดยไฮไลต์ไอคอน "แชร์"
รูปที่ 6 แถวไอคอนที่คลิกได้โดยมีไอคอน "แชร์" เลือกไว้

เฟรมเวิร์ก 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 มีไว้สำหรับใช้กับองค์ประกอบกราฟิกเป็นหลัก เช่น รูปภาพ คอมโพเนนต์ของ Material เช่น Button หรือ Text และลักษณะการทำงานที่ดำเนินการได้ เช่น clickable หรือ toggleable มาพร้อมกับความหมายอื่นๆ ที่กําหนดไว้ล่วงหน้าซึ่งอธิบายลักษณะการทํางานโดยพื้นฐาน และสามารถเปลี่ยนแปลงผ่าน Compose API อื่นๆ

องค์ประกอบแบบอินเทอร์แอกทีฟ

Material และ Foundation Compose API สร้างองค์ประกอบ UI ที่ผู้ใช้โต้ตอบได้ผ่าน API ของตัวแก้ไข clickable และ toggleable เนื่องจากคอมโพเนนต์ที่โต้ตอบได้อาจประกอบด้วยองค์ประกอบหลายรายการ clickable และ toggleable จึงผสานความหมายขององค์ประกอบย่อยโดยค่าเริ่มต้น เพื่อให้ระบบถือว่าคอมโพเนนต์เป็นเอนทิตีเชิงตรรกะรายการเดียว

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

ปุ่มที่มีความหมายขององค์ประกอบย่อยแบบผสานและไม่ผสาน
รูปที่ 7 ปุ่มที่มีความหมายขององค์ประกอบย่อยแบบผสานและไม่ผสาน

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

Row(
    // Uses `mergeDescendants = true` under the hood
    modifier = Modifier.clickable { openArticle() }
) {
    Icon(
        painter = painterResource(R.drawable.ic_logo),
        contentDescription = "Open",
    )
    Text("Accessibility in Compose")
}

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

Row(
    modifier = Modifier
        .clickable(onClickLabel = "Open this article") {
            openArticle()
        }
) {
    Icon(
        painter = painterResource(R.drawable.ic_logo),
        contentDescription = "Open"
    )
    Text("Accessibility in Compose")
}

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

ความคิดเห็นนี้จะเปลี่ยนแปลงไปตามประเภทการดําเนินการ การแตะค้างไว้จะแสดงคำแนะนำของ TalkBack ว่า "แตะสองครั้งที่ค้างไว้เพื่อ" ตามด้วยป้ายกำกับ

Row(
    modifier = Modifier
        .combinedClickable(
            onLongClickLabel = "Bookmark this article",
            onLongClick = { addToBookmarks() },
            onClickLabel = "Open this article",
            onClick = { openArticle() },
        )
) {}

ในบางกรณี คุณอาจไม่มีสิทธิ์เข้าถึงตัวแก้ไข clickable โดยตรง (เช่น เมื่อตั้งค่าไว้ที่ใดที่หนึ่งในเลเยอร์ที่ฝังอยู่ต่ำกว่า) แต่ยังคงต้องการเปลี่ยนป้ายกํากับประกาศจากค่าเริ่มต้น โดยแยกการตั้งค่า clickable ออกจากการแก้ไขประกาศโดยใช้ตัวแก้ไข semantics และตั้งค่าป้ายกํากับการคลิกที่นั่นเพื่อแก้ไขการนําเสนอการกระทํา

@Composable
private fun ArticleList(openArticle: () -> Unit) {
    NestedArticleListItem(
        // Clickable is set separately, in a nested layer:
        onClickAction = openArticle,
        // Semantics are set here:
        modifier = Modifier.semantics {
            onClick(
                label = "Open this article",
                action = {
                    // Not needed here: openArticle()
                    true
                }
            )
        }
    )
}

ในกรณีนี้ คุณไม่จําเป็นต้องส่งการดําเนินการคลิก 2 ครั้ง เนื่องจาก Compose API ที่มีอยู่ เช่น clickable หรือ Button จะจัดการเรื่องนี้ให้คุณ เนื่องจากตรรกะการผสานจะนําป้ายกำกับและการดำเนินการที่ด้านนอกสุดมาใช้กับข้อมูลที่แสดงอยู่

ในตัวอย่างก่อนหน้านี้ NestedArticleListItem จะส่งการดําเนินการคลิก openArticle() ไปยัง clickable Semantics โดยอัตโนมัติ และสามารถปล่อยค่าว่างไว้ในการดําเนินการตัวแก้ไข Semantics รายการที่ 2 อย่างไรก็ตาม ป้ายกํากับการคลิกจะนํามาจากตัวแก้ไขความหมายที่ 2 onClick(label = "Open this article") เนื่องจากไม่มีอยู่ในรายการแรก

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

คอมโพเนนต์ที่กําหนดเอง

สําหรับคอมโพเนนต์ที่กําหนดเอง กฎง่ายๆ คือดูการใช้งานคอมโพเนนต์ที่คล้ายกันในไลบรารี Material หรือไลบรารี Compose อื่นๆ และเลียนแบบหรือแก้ไขลักษณะการช่วยเหลือพิเศษของคอมโพเนนต์นั้นตามความเหมาะสม

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

นอกจากนี้ ให้ใช้ตัวปรับเปลี่ยนของ Foundation อย่างมาก เนื่องจากมีการพิจารณาการช่วยเหลือพิเศษอยู่แล้ว รวมถึงแนวทางปฏิบัติของ Compose ที่มีอยู่ซึ่งกล่าวถึงในส่วนนี้

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