Compose のユーザー補助機能を改善する主な手順

ユーザー補助機能を必要とするユーザーがアプリを適切に使用できるように、 主要なユーザー補助機能の要件に対応できます。

タップ ターゲットの最小サイズを検討する

クリック、タップなど、ユーザーが操作できる画面上の要素はすべて、確実に操作できるよう十分な大きさにする必要があります。これらの要素のサイズを設定する際は、 マテリアル デザインに沿って最小サイズを 48 dp に設定する ユーザー補助ガイドラインをご覧ください。

マテリアル コンポーネント(CheckboxRadioButtonSwitchSliderSurface - この最小サイズを内部で設定します。ただし、 コンポーネントがユーザー操作を受け取れる条件を指定します。たとえば、CheckboxonCheckedChange パラメータが null 以外の値に設定されている場合、このチェックボックスには 幅と高さを 48 dp 以上にする必要があります。

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

onCheckedChange パラメータが null に設定されている場合、パディングは調整されません。 コンポーネントを直接操作できないためです。

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

<ph type="x-smartling-placeholder">
</ph>
図 1.パディングなしのチェックボックス。

選択コントロール(SwitchRadioButtonCheckbox の場合、通常はクリック可能な動作を親コンテナにリフトします。 コンポーザブルのクリック コールバックを null に設定し、toggleable または selectable 修飾子を親コンポーザブルに追加します。

@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)
        }
    }
}

クリック可能なコンポーザブルのサイズがタップ ターゲットの最小サイズより小さい場合、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)
        )
    }
}

異なるコンポーザブルのタッチ領域間で重複が発生するのを防ぐには、常に コンポーザブルに十分な大きさの最小サイズを使用します。この例では、 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)
        )
    }
}

クリックラベルを追加する

クリックラベルを使用して、コンポーザブルのクリック動作に意味論的意味を追加できます。クリックラベルは、ユーザーが 作成します。ユーザー補助サービスでは、クリックラベルを使用してアプリの説明をお手伝いします。 サポートしています。

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)
        }
    ) {
        // ..
    }
}

視覚要素を説明する

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 やスイッチ アクセスなどのユーザー補助サービスでは、ユーザーは画面上の要素間でフォーカスを移動できます。適切な粒度で要素がフォーカスされることが重要です。画面上のすべての低レベルのコンポーザブルが、 フォーカスが独立しているため、ユーザーは画面上を移動するために何度も操作する必要があります。 過度に積極的に要素を結合すると、ユーザーは 要素は同じ

コンポーザブルに clickable 修飾子を適用すると、Compose が コンポーザブルに含まれるすべての要素を自動的に結合します。これは ListItem、要素を結合することで、より効率的に サービスはそれらを 1 つの要素とみなします。

論理グループを形成するコンポーザブルのセットを持つことはできますが、そのグループはクリック可能ではなく、リストアイテムの一部でもありません。アクセシビリティと 1 つの要素として表示できます。たとえば、24 時間 365 日の は、ユーザーのアバター、名前、その他の情報を表示します。

ユーザー名を含む UI 要素のグループ。名前が選択されています。

mergeDescendants を使用すると、Compose でこれらの要素を結合できるようになります。 パラメータで 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 { }
        )
    }
}

要素の状態について説明する

コンポーザブルでは、セマンティクスのために stateDescription を定義できます。 Android フレームワークは、コンポーザブルの状態の読み上げに使用します。対象 たとえば切り替え可能なコンポーザブルはまたは「オフ」 あります。場合によっては、デフォルトの状態の説明をオーバーライドする必要がある ラベルを定義します。そのためには、状態を明示的に指定すると、 説明ラベルを確認しておく必要があります。

@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() }
            )
    ) {
        /* ... */
    }
}

見出しを定義する

アプリは、スクロール可能なコンテナの 1 つの画面に多くのコンテンツを表示することがあります。 たとえば、1 つの画面にユーザーが読んでいる記事のすべての内容を表示する場合などです。

スクロール可能なコンテナで記事テキストを表示したブログ投稿のスクリーンショット。

ユーザー補助を必要とするユーザーは、そのような画面を操作するのが困難です。支援 見出しとなる要素を指定します。上の例では、 サブセクションのタイトルをユーザー補助の見出しとして定義できます。一部 TalkBack などのユーザー補助サービスでは、ユーザーが 見出しに見出します。

Compose では、コンポーズ可能な要素を見出しとして示すために、 semantics プロパティ:

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

カスタム コンポーザブルを処理する

アプリ内の特定のマテリアル コンポーネントをカスタム 使用する場合は、ユーザー補助に関する考慮事項に留意する必要があります。

マテリアル Checkbox を独自の実装に置き換えるとします。 triStateToggleable 修飾子を付け忘れても、この修飾子は このコンポーネントのユーザー補助機能の プロパティを指定します

目安として、 マテリアル ライブラリを使用して、ユーザー補助動作を模倣できます。 また、UI レベルではなく、Foundation 修飾子を多用します。 修飾子が最初から組み込まれています。

カスタム コンポーネントの実装を複数の ユーザー補助サービスを使用して、その動作を検証できます。

参考情報