[Перевод] Реализация доступности с помощью Flutter

В этой статье поговорим о том, как Flutter делает приложения с рендерингом на холсте доступными для пользователей вспомогательных технологий.

Веб является одной из целевых платформ, поддерживаемых фреймворком Flutter. Приложения на Flutter обеспечивают идеальное отображение пикселей и согласованность с платформой благодаря рендерингу всего пользовательского интерфейса на элементе canvas. Однако по умолчанию элементы canvas недоступны. В этой публикации рассмотрим, как поддержка доступности работает для приложений на Flutter, рендеринг которых выполняется на холсте.

Во Flutter есть большое количество виджетов по умолчанию, которые генерируют дерево доступности автоматически. Дерево доступности представляет собой дерево объектов доступности, к которым вспомогательные технологии могут обращаться за атрибутами и свойствами и выполнять действия. Для настраиваемых виджетов класс Semantics позволяет разработчикам описывать значение своих виджетов, помогая вспомогательным технологиям понять смысл содержимого виджетов.

Из соображений производительности, на момент написания данного текста доступность в Flutter включается по умолчанию только при явном запросе. Команда Flutter хотела бы со временем включить семантику в Flutter Web по умолчанию. Однако на данный момент это приведет к заметному снижению производительности в значительном количестве случаев и требует некоторой оптимизации, прежде чем значение по умолчанию можно будет изменить. Разработчики, которые хотят всегда включать режим доступности во Flutter, могут сделать это с помощью следующего фрагмента кода.

import 'package:flutter/semantics.dart';

void main() {
  runApp(const MyApp());
  if (kIsWeb) {
    SemanticsBinding.instance.ensureSemantics();
  }
}

Примечание: Если вашему приложению необходимо знать, использует ли пользователь такие устройства, как скринридеры, позвольте пользователям дать явное согласие.

Как только вы включите поддержку доступности в Flutter, HTML будет автоматически изменяться, как показано далее на этой странице.

Примечание: скринридеры — это только один пример вспомогательной технологии, которая выигрывает от описанного подхода. Cкринридеры используются как прокси для этой и других вспомогательных технологий для улучшения читаемости.

Включение поддержки доступности в Flutter

Механизм явного включения в Flutter реализуется с помощью скрытой кнопки. Он помещает кнопку, а точнее, элемент с role="button" — невидимый и недоступный для зрячих пользователей — в HTML. Это настраиваемый элемент с наложенным стилем, поэтому он не отображается и не выбирается, если вы не используете скринридер.

/* `` inherits from ``. */
flutter-view {
  user-select: none;
}

Изменения после включения

Что происходит, когда пользователь скринридера нажимает на эту кнопку? Рассмотрим на примере карточки из галереи Flutter, как показано на следующем скриншоте.

A classic card component with an image, a heading, and some text.

Классический компонент карточки с изображением, заголовком и текстом.

Чтобы лучше понять, что конкретно меняется, когда пользователь нажимает на кнопку, сравните скриншоты до и после в Chrome DevTools, изучая дерево доступности. Второй скриншот раскрывает гораздо больше семантической информации, чем первый.

До явного включения:

Chrome DevTools showing an

В Chrome DevTools появилась кнопка «Включить доступность».

После явного включения:

Chrome DevTools showing a rich accessibility tree with headings, buttons, groups, etc.

Chrome DevTools показывает богатое дерево доступности с заголовками, кнопками, группами и т. д.

Детали реализации

Основная идея Flutter заключается в создании доступной структуры DOM, которая отражает то, что в данный момент отображается на холсте. Это включает в себя родительский элемент , который содержит дочерние элементы и , которые, в свою очередь, могут быть вложены друг в друга. Рассмотрим виджет кнопки, например TextButton. Этот виджет представлен элементом в DOM. Аннотации ARIA (например, role или aria-label) и другие свойства DOM (tabindex, слушатели событий) на элементе позволяют скринридеру объявлять пользователю элемент как кнопку, а также поддерживать щелчки и тапы по нему, даже если это не буквально элемент