Flutter 的無障礙設計:Semantics 深入剖析

發布於 2023-10-05  196 次瀏覽


AI 摘錄

本文章講述了Flutter中的無障礙設計,特別聚焦在Semantics元件上。Semantics是一個核心的widget,它將應用的介面和輔助技術工具連接起來,如螢幕閱讀器和語音助手。通過Semantics,開發者可以提供關於應用中各個元件的語義信息,以幫助需要輔助技術的使用者更好地理解和操作應用。 Semantics的功能包括封裝和傳遞子widget的語義信息,例如元件的類型、狀態、行為以及名稱、描述或值等。開發者可以通過Semantics的屬性來設定這些語義信息。 文章也介紹了如何覆蓋或修改默認的語義行為。例如,使用螢幕閱讀器時,Image元件會被自動標記為圖片並添加相應的描述。但在某些情況下,開發者可能需要提供更具描述性或特定的語義訊息。Flutter提供了excludeSemantics屬性,讓開發者可以排除子樹中的所有語義,以提供更準確或有用的語義信息。 最後,文章提醒開發者通過合理利用Semantics,可以為應用提供豐富而準確的語義信息,提升無障礙設計的水準,從而讓更多人能夠輕鬆使用數位科技。

前言

在現今數位化飛速進展的時代,無障礙設計已不僅僅是道德的考量,有時更是專案要求或企業的社會責任。特別是在政府的專案中,大多數都要求行動應用必須實作無障礙功能並通過相關檢測。而對於使用者來說,一個容易操作、可達性強的介面能大大提升其使用經驗。無障礙設計實際上是在建立一個每個人都能輕鬆使用的環境,無論他們是否有視覺、聽覺或動作上的困難。透過無障礙設計,我們能讓更多人不受限地享受數位科技的便利。在這裡,我們將深入探討 Flutter 這個熱門的跨平台開發框架如何實現無障礙功能,特別聚焦在 Semantics 這個元件上。

基礎知識:什麼是 Semantics?

在 Flutter 中,Semantics 是一個非常核心的 widget,它扮演著橋樑的角色,連接了應用的介面與輔助技術工具,如螢幕閱讀器和語音助手。通過 Semantics widget,開發者能夠提供關於應用中各個元件的語義信息,以協助那些需要輔助技術的使用者更好地理解和操作應用。

Semantics widget 的主要功能是封裝和傳遞關於其子 widget 的語義信息。這些語義信息可以包括但不限於:

  • 元件的類型(如按鈕、連結或標籤)
  • 元件的狀態(如是否被選中、禁用或聚焦)
  • 元件的行為(如可以點擊、滑動或拖放)
  • 元件的名稱、描述或值

下面是一個簡單的例子來展示 Semantics 的基本用法:

Semantics(
  button: true,
  enabled: true,
  label: "提交表單",
  onTap: () {
    if (kDebugMode) {
      print("Form submitted");
    }
  },
  child: TextButton(
    onPressed: () {
      if (kDebugMode) {
        print("Form submitted");
      }
    },
    child: const Text("Submit"),
  ),
)

在這個例子中,我們創建了一個 Semantics widget 並且將一個 TextButton widget 作為它的子元件。我們通過 Semantics 的屬性來定義了一些語義信息,例如這個元件是一個按鈕(button: true),它是可用的(enabled: true),它有一個名為“提交表單”的標籤(label: "提交表單"),以及它有一個點擊事件(onTap 方法)。這樣,當使用螢幕閱讀器的使用者操作這個按鈕時,他們會聽到“提交表單按鈕”,並且知道它是可以被點擊的。

透過這種方式,Semantics widget 為開發者提供了一個強大而靈活的工具,以確保他們的應用能夠更好地服務於所有人,不僅僅是那些無障礙需求的使用者。在開發過程中,通過合理地利用 Semantics widget,我們能夠為我們的應用提供豐富而準確的語義信息,從而提升無障礙設計的水準。

深化理解 Semantics:覆蓋默認語義行為

在 Flutter 應用開發中,有時候我們會遇到需要覆蓋或修改默認語義行為的情境。例如,當使用螢幕讀取器如 Android 的 TalkBack 或 iOS 的 VoiceOver 時,Image 小部件會自動被標記為圖片,並且在描述中添加"圖片"這個詞。然而,在某些情境下,我們可能想要提供更具描述性或特定的語義信息,而非默認的標籤。

Flutter 提供了 excludeSemantics 屬性,讓我們能夠覆蓋這種默認行為。excludeSemantics 屬性允許我們排除子樹中的所有語義,這樣螢幕讀取器就不會讀取默認的語義描述,例如"圖片"這個詞。通過這種方式,我們可以為視覺受限的使用者提供更為準確或有用的語義信息。

讓我們通過一個實例來深入了解如何利用 excludeSemantics 屬性來覆蓋默認的語義描述:

Semantics(
  label: '行動平台 Logo',
  child: const Padding(
    padding: EdgeInsets.only(left: 24),
    child: ExcludeSemantics(
      child: Image(image: AssetImage('assets/images/logo_white.png')),
    ),
  ),
)

在上述例子中,我們首先創建了一個 Semantics widget 並指定了 label 屬性為 "行動平台 Logo"。接著,我們為 Semantics widget 的 child 屬性提供了一個 Padding widget,以確保 Image widget 有適當的邊距。最後,我們使用 ExcludeSemantics widget 來包裹 Image widget,以排除 Image widget 的默認語義信息。

通過 ExcludeSemantics widget,我們成功地覆蓋了 Image widget 的默認語義描述。現在,當使用者通過螢幕讀取器來訪問這個元件時,他們會聽到 "行動平台 Logo" 而不是默認的 "圖片" 描述。這樣的設計不僅提供了更為準確的語義信息,也提升了應用的無障礙友善度,使得視覺受限的使用者能夠更好地理解和使用我們的應用。

利用 Semantics 控制焦點順序

在 Flutter 中,你可以利用 SemanticssortKey 參數來控制焦點順序。通常情況下,我們會使用 OrdinalSortKey 來指定焦點順序。以下是一個簡單的範例來展示如何操作:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('焦點順序範例'),
        ),
        body: FocusTraversalGroup(
          child: Column(
            children: [
              Semantics(
                sortKey: OrdinalSortKey(1.0),
                child: TextField(
                  decoration: InputDecoration(
                    hintText: '第一個欄位',
                  ),
                ),
              ),
              Semantics(
                sortKey: OrdinalSortKey(0.0),
                child: TextField(
                  decoration: InputDecoration(
                    hintText: '第二個欄位',
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

在這個範例中,我們建立了兩個 TextField 控件,並分別將它們包裹在 Semantics 控件中。我們為 Semantics 控件提供了 sortKey 參數,並利用 OrdinalSortKey 類別來指定排序順序。OrdinalSortKey 的值越小,焦點順序就越高,所以在這個範例中,焦點會首先移動到 "第二個欄位",然後再移動到 "第一個欄位"。

焦點順序與 sortKey

如果在應用中有五個元件,但只有兩個元件使用了 sortKey 屬性來指定焦點順序,那麼這兩個元件會根據指定的 sortKey 值來排序,而其它三個未指定 sortKey 的元件則會按照它們在樹中的位置來確定焦點順序。

sortKey 是一種明確指定焦點順序的方法,而在沒有 sortKey 的情況下,焦點順序會依賴於元件樹的結構。具體來說,焦點通常會按照元件在樹中的順序從上到下,從左到右進行遍歷。

例如,如果你的元件樹如下所示,其中只有元件 B 和元件 D 使用了 sortKey

  • 元件 A(未使用 sortKey
  • 元件 B(使用 sortKey,值為 1.0)
  • 元件 C(未使用 sortKey
  • 元件 D(使用 sortKey,值為 0.0)
  • 元件 E(未使用 sortKey

在這種情況下,焦點順序會是這樣的:

  1. 元件 D(因為它的 sortKey 值最小)
  2. 元件 B(因為它的 sortKey 值次之)
  3. 元件 A(按照元件樹的順序,它是下一個元件)
  4. 元件 C(繼續按照元件樹的順序)
  5. 元件 E(最後一個元件)

通過這個設計,我們可以輕鬆地控制應用中的焦點順序,使得使用者在遷移焦點時能夠有更流暢、直觀的操作體驗。這對於無障礙設計來說,是非常重要且實用的一個功能。

結論

無障礙設計是開發過程中不可忽視的一環,它不僅僅是法律規定的要求,在很多政府或公共領域的專案中更是常見的需求。通過 Semantics widget,Flutter 提供了一個直觀而強大的工具,讓開發者能夠輕鬆地為其應用提供豐富的語義信息,以支援輔助技術工具如螢幕閱讀器和語音助手。在我們提供的範例中,可以看出,只需透過簡單的 Semantics 配置,就能大大提高應用的無障礙友善度,使視力受損或其他需要輔助技術的使用者能夠更容易地使用我們的應用。進一步來說,無障礙設計也體現了開發者的社會責任和道德關懷,它使得數位產品能夠服務於所有人群,不分能力或環境。透過無障礙設計,我們的應用不僅技術上更加成熟,也在人文關懷上達到了新的高度。希望透過這篇文章,你能深刻理解到無障礙設計的重要性,並能夠在未來的開發中將其付諸實踐。