Skip to content

[A11y]: Slider labels not included in the Semantics widget #162067

Closed

Description

@ChrisCRCB

Steps to reproduce

When creating Slider widgets, the Slider.label information isn't passed to the semantics widget.

Expected results

Sliders should announce their labels when tabbing through with a screen reader such as NVDA. I can't test platforms other than Windows or Chrome while at work.

Actual results

NVDA announces "Slider", then the percentage.

The third slider works perfectly. Looking at the implementation of the Slider widget, it seems that there is no label property being passed to the Semantics widget at the end of the _buildMaterialSlider method.

I've tested this locally, and adding the label argument fixes this.
Am I OK to submit a PR with this change? I don't really know how all of this works. I'm keen to help, but - depending on how much vetting I'll need - it might be quicker for someone else to add label: widget.label to line 1083 of slider.dart. 😄

Thank you for a wonderful framework!!

Code sample

Code sample
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    final renderBinding = RendererBinding.instance;
    if (!renderBinding.semanticsEnabled) {
      renderBinding.ensureSemantics();
    }
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    const divider = 100;
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text('$_counter'),
            Slider(
              autofocus: true,
              value: _counter / divider,
              onChanged: (value) => setState(
                () => _counter = (value * divider).round(),
              ),
              label: 'Screen readers will not pick up this label',
            ),
            Slider(
              value: _counter / divider,
              onChanged: (value) => setState(
                () => _counter = (value * divider).round(),
              ),
              label: 'Screen readers will not speak this label either',
              semanticFormatterCallback: (value) =>
                  'Screen readers will show this value. Counter is $_counter',
            ),
            MergeSemantics(
              // I use `MergeSemantics` to prevent NVDA from recognising a group.
              child: Semantics(
                label: 'This works perfectly',
                child: Slider(
                  value: _counter / divider,
                  onChanged: (value) => setState(
                    () => _counter = (value * divider).round(),
                  ),
                  label:
                      'We just need to wrap the `Slider` widget in a `MergeSemantics` and a `Semantics` widget and everything will be fixed',
                ),
              ),
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs

Flutter Doctor output

Doctor output
[Γ£ô] Flutter (Channel master, 3.28.0-2.0.pre.38833, on Microsoft Windows [Version 10.0.26100.2894], locale en-GB) [2.5s]
    ΓÇó Flutter version 3.28.0-2.0.pre.38833 on channel master at C:\Users\chris\flutter
    ΓÇó Upstream repository https://github.com/flutter/flutter
    ΓÇó Framework revision 97ca57cf08 (6 hours ago), 2025-01-23 06:38:20 +0100
    ΓÇó Engine revision 97ca57cf08
    ΓÇó Dart version 3.8.0 (build 3.8.0-24.0.dev)
    ΓÇó DevTools version 2.42.0

[Γ£ô] Windows Version (11 Home 64-bit, 24H2, 2009) [4.1s]

[Γ£ô] Android toolchain - develop for Android devices (Android SDK version 34.0.0) [4.4s]
    ΓÇó Android SDK at C:\Users\chris\AppData\Local\Android\sdk
    ΓÇó Platform android-35, build-tools 34.0.0
    ΓÇó Java binary at: C:\Program Files\Android\Android Studio\jbr\bin\java
      This is the JDK bundled with the latest Android Studio installation on this machine.
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
    ΓÇó Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-9586694)
    ΓÇó All Android licenses accepted.

[Γ£ô] Chrome - develop for the web [119ms]
    ΓÇó Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[Γ£ô] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.12.4) [117ms]
    ΓÇó Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
    ΓÇó Visual Studio Community 2022 version 17.12.35707.178
    ΓÇó Windows 10 SDK version 10.0.22621.0

[Γ£ô] Android Studio (version 2022.2) [16ms]
    ΓÇó Android Studio at C:\Program Files\Android\Android Studio
    ΓÇó Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    ΓÇó Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    ΓÇó Java version OpenJDK Runtime Environment (build 17.0.6+0-b2043.56-9586694)

[Γ£ô] VS Code, 64-bit edition (version 1.96.2) [14ms]
    ΓÇó VS Code at C:\Program Files\Microsoft VS Code
    ΓÇó Flutter extension version 3.102.0

[Γ£ô] Connected device (3 available) [290ms]
    ΓÇó Windows (desktop) ΓÇó windows ΓÇó windows-x64    ΓÇó Microsoft Windows [Version 10.0.26100.2894]
    ΓÇó Chrome (web)      ΓÇó chrome  ΓÇó web-javascript ΓÇó Google Chrome 131.0.6778.265
    ΓÇó Edge (web)        ΓÇó edge    ΓÇó web-javascript ΓÇó Microsoft Edge 132.0.2957.115

[Γ£ô] Network resources [412ms]
    ΓÇó All expected network resources are available.

ΓÇó No issues found!

Activity

  1. changed the title [-][A11y]: Slider labels not incuded in the `Semantics` widget[/-] [+][A11y]: Slider labels not included in the `Semantics` widget[/+] on Jan 23, 2025
  2. added
    in triagePresently being triaged by the triage team
    on Jan 24, 2025
  3. huycozy commented on Jan 24, 2025

    @huycozy
    Member

    Hi @ChrisCRCB
    I check this on iOS with VoiceOver and can hear it announce Slider label as expected:This works perfectly.

    Can you confirm this issue only occurs with NVDA reader on Windows? Can you help test this with JAWS or Narrator as well? Thanks!

  4. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Jan 24, 2025
  5. ChrisCRCB commented on Jan 24, 2025

    @ChrisCRCB
    ContributorAuthor

    Hi @huycozy,
    That is the semantic label for the third slider, not its actual label. What do you hear announced for the first two please? It's still not working as it should.

  6. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Jan 24, 2025
  7. darshankawar commented on Jan 28, 2025

    @darshankawar
    Member

    @ChrisCRCB
    Please check if this helps further in your case or not.

  8. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Jan 28, 2025
  9. ChrisCRCB commented on Jan 28, 2025

    @ChrisCRCB
    ContributorAuthor

    @darshankawar
    I have no idea if the labels are visible or not. All I know is they are not present semantically. I don't know how to reference a file with lines, so I'll just paste the relevant portion of the code here:

        return Semantics(
          container: true,
          slider: true,
          onDidGainAccessibilityFocus: handleDidGainAccessibilityFocus,
          child: FocusableActionDetector(
            actions: _actionMap,
            shortcuts: shortcutMap,
            focusNode: focusNode,
            autofocus: widget.autofocus,
            enabled: _enabled,
            onShowFocusHighlight: _handleFocusHighlightChanged,
            onShowHoverHighlight: _handleHoverChanged,
            mouseCursor: effectiveMouseCursor,
            child: result,
          ),
        );

    That is from line 991 of packages/flutter/lib/src/material/slider.dart.

  10. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Jan 28, 2025
  11. ChrisCRCB commented on Jan 28, 2025

    @ChrisCRCB
    ContributorAuthor

    Sorry, meant to say: If you read the block, you'll note that label: is not present.

    I'd argue that even if the label is not visible, it should be present semantically, to maximise the chances that assistive technologies know what it is without needing to worry about any other visual context which is programmed in.

  12. darshankawar commented on Jan 29, 2025

    @darshankawar
    Member

    MergeSemantics(
    // I use MergeSemantics to prevent NVDA from recognising a group.
    child: Semantics(
    label: 'This works perfectly',

    I observed that this label is read properly, but not the below ones:

    Slider(
    value: _counter / divider,
    onChanged: (value) => setState(
    () => _counter = (value * divider).round(),
    ),
    label: 'Screen readers will not speak this label either',

    I verified on chrome with accessibility. Keeping the issue open for team's tracking.

    stable : 3.27.3
    master : 3.29.0-1.0.pre.127
    
  13. added
    frameworkflutter/packages/flutter repository. See also f: labels.
    p: material_uimaterial_ui package in flutter/packages
    a: accessibilityAccessibility, e.g. VoiceOver or TalkBack. (aka a11y)
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    team-accessibilityOwned by Framework Accessibility team (i.e. responsible for accessibility code in flutter/flutter)
    and removed
    in triagePresently being triaged by the triage team
    on Jan 29, 2025
  14. added a commit that references this issue on Jan 30, 2025
    4619574
  15. added
    r: fixedIssue is closed as already fixed in a newer version
    on Jan 31, 2025
  16. github-actions commented on Feb 14, 2025

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  17. locked as resolved and limited conversation to collaborators on Feb 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    a: accessibilityAccessibility, e.g. VoiceOver or TalkBack. (aka a11y)found in release: 3.27Found to occur in 3.27found in release: 3.29Found to occur in 3.29frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onp: material_uimaterial_ui package in flutter/packagesr: fixedIssue is closed as already fixed in a newer versionteam-accessibilityOwned by Framework Accessibility team (i.e. responsible for accessibility code in flutter/flutter)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions