Skip to content

Add new motion accessibility features to iOS.#178102

Merged
auto-submit[bot] merged 24 commits intoflutter:masterfrom
ksokolovskyi:add-new-ios-accessibility-features
Jan 8, 2026
Merged

Add new motion accessibility features to iOS.#178102
auto-submit[bot] merged 24 commits intoflutter:masterfrom
ksokolovskyi:add-new-ios-accessibility-features

Conversation

@ksokolovskyi
Copy link
Contributor

@ksokolovskyi ksokolovskyi commented Nov 6, 2025

Closes #177330
Contributes to #175878

Description

This PR implements support for three new iOS accessibility motion features.

  • Auto-Play Animated Images: Informs the app when the user has chosen to pause automatically playing GIFs and other animated content.
  • Auto-Play Video Previews: Informs the app when the user has disabled the automatic playback of video previews.
  • Prefer Non-Blinking Cursor: Informs the app that the user prefers a non-blinking text insertion indicator in editable text fields.

The original issue requested seven features. I was able to find and implement features with clear, public, and general-purpose APIs.

The remaining features were not included for the following reasons:

  • Vehicle Motion Cues: No public API found.
  • Auto-Play Message Effects: No public API found. This is likely a feature exclusive to the Messages framework.
  • Limit Frame Rate: No public API found.
  • Dim Flashing Lights: There is a public API available MADimFlashingLightsEnabled. It is intended for media playback frameworks. It's unclear if exposing this feature is necessary or actionable for a general-purpose application UI.
Feature Name API Flutter AccessibilityFeatures
Vehicle Motion Cues - -
Dim Flashing Lights MADimFlashingLightsEnabled -
Auto-Play Animated Images animatedImagesEnabled autoPlayAnimatedImages
Auto-Play Video Previews isVideoAutoplayEnabled autoPlayVideos
Auto-Play Message Effects - -
Prefer Non-Blinking Cursor prefersNonBlinkingTextInsertionIndicator deterministicCursor
Limit Frame Rate - -

The AccessibilityFeatures.swift was introduced to refactor all native iOS accessibility logic into a single, dedicated class. This change moves the responsibility of querying settings and observing notifications out of FlutterViewController.mm, which cleans up the controller, simplifies future maintenance, and makes logic unit-testable.

Demo

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

void main() {
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Screen(),
    ),
  );
}

class Screen extends StatefulWidget {
  @override
  State<Screen> createState() => _ScreenState();
}

class _ScreenState extends State<Screen> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void didChangeAccessibilityFeatures() {
    super.didChangeAccessibilityFeatures();
    if (mounted) {
      setState(() {});
    }
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final accessibilityFeatures = View.of(
      context,
    ).platformDispatcher.accessibilityFeatures;

    return Scaffold(
      body: Center(
        child: Column(
          spacing: 10,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            for (final feature in [
              'accessibleNavigation: ${accessibilityFeatures.accessibleNavigation}',
              'invertColors: ${accessibilityFeatures.invertColors}',
              'disableAnimations: ${accessibilityFeatures.disableAnimations}',
              'boldText: ${accessibilityFeatures.boldText}',
              'reduceMotion: ${accessibilityFeatures.reduceMotion}',
              'highContrast: ${accessibilityFeatures.highContrast}',
              'onOffSwitchLabels: ${accessibilityFeatures.onOffSwitchLabels}',
              'supportsAnnounce: ${accessibilityFeatures.supportsAnnounce}',
              'autoPlayAnimatedImages: ${accessibilityFeatures.autoPlayAnimatedImages}',
              'autoPlayVideos: ${accessibilityFeatures.autoPlayVideos}',
              'deterministicCursor: ${accessibilityFeatures.deterministicCursor}',
            ])
              Text(feature),
          ],
        ),
      ),
    );
  }
}

Pre-launch Checklist

@github-actions github-actions bot added a: tests "flutter test", flutter_test, or one of our tests platform-android Android applications specifically platform-ios iOS applications specifically framework flutter/packages/flutter repository. See also f: labels. engine flutter/engine related. See also e: labels. a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) platform-web Web applications specifically team-android Owned by Android platform team team-ios Owned by iOS platform team labels Nov 6, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for new iOS accessibility features: autoPlayAnimatedImages, autoPlayVideoPreviews, and nonBlinkingCursor. The implementation includes a good refactoring of the iOS accessibility feature handling by introducing a new AccessibilityFeatures.swift class, which encapsulates the logic for querying native accessibility settings. This improves code organization and readability. The changes are consistently applied across different parts of the engine. I have one suggestion to improve the clarity of the public embedder API. Also, the table in the pull request description seems to be a placeholder and could be filled out.

@@ -0,0 +1,217 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this is quite nice and clean, is there a reason we are doing this pretty significant refactoring in this PR? it seems a bit out of scope, for this feature.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also tagging @hannah-hyj who I seem to remember did some work refactoring accessibility flags for potential input

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking a look at this PR!

The new iOS 18 features require Apple's AccessibilitySettings API, which is Swift-only.

Since I had to add a Swift file to use this new API, I chose to consolidate all accessibility logic into it. The alternative would have been to split the logic across both FlutterViewController.m and this new Swift file, which felt less maintainable.

This approach keeps all related code in one place and makes the logic testable. Happy to discuss splitting it out if you still think it's best.

@chunhtai chunhtai self-requested a review November 12, 2025 22:47
/// Always returns `true` on other platforms.
// This index check is inverted (== 0 vs != 0) since most of the platforms
// don't have an option to disable animated images auto play.
bool get autoPlayAnimatedImages => _kNoAutoPlayAnimatedImagesIndex & _index == 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this also apply to gifs? If so we may need to wire this up to image widget. but that should probably be a separate PR cc @justinmc since you worked on that widget recently

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like yes this is for gifs: https://developer.apple.com/documentation/accessibility/animated-images

I've created an issue: #180395

@mdebbar mdebbar requested a review from flutter-zl November 19, 2025 19:18
@chunhtai
Copy link
Contributor

google test failure doesn't seem related, @ksokolovskyi can you try rebase again?

@github-actions github-actions bot added the team-android Owned by Android platform team label Jan 5, 2026
@mdebbar mdebbar added the triaged-web Triaged by Web platform team label Jan 7, 2026
Copy link
Contributor

@LouiseHsu LouiseHsu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ios parts lgtm!

@chunhtai chunhtai added the autosubmit Merge PR when tree becomes green via auto submit App label Jan 8, 2026
@auto-submit auto-submit bot added this pull request to the merge queue Jan 8, 2026
Merged via the queue into flutter:master with commit 3892c57 Jan 8, 2026
181 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jan 8, 2026
@chrisbobbe
Copy link
Contributor

Thanks everyone! 🎉

engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 9, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 9, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 9, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 9, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 10, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 10, 2026
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 10, 2026
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Jan 10, 2026
Roll Flutter from 01d37bc to 73769a2 (65 revisions)

flutter/flutter@01d37bc...73769a2

2026-01-10 [email protected] Roll Dart SDK from 5e855c2bb3ef to 87fbfd5381b6 (1 revision) (flutter/flutter#180800)
2026-01-10 [email protected] Roll Skia from b2b109f0e980 to f39cc645b1dd (2 revisions) (flutter/flutter#180796)
2026-01-10 [email protected] Roll Dart SDK from b7963905e6a2 to 5e855c2bb3ef (2 revisions) (flutter/flutter#180794)
2026-01-10 [email protected] Make sure that a CupertinoTabScaffold doesn't crash in 0x0 environment (flutter/flutter#179824)
2026-01-10 [email protected] Roll Dart SDK from d25ad331b7ea to b7963905e6a2 (2 revisions) (flutter/flutter#180783)
2026-01-10 [email protected] Make sure that a Container doesn't crash in 0x0 environment (flutter/flutter#180350)
2026-01-10 [email protected] Make sure that an Expansible doesn't crash in 0x0 environment (flutter/flutter#180478)
2026-01-10 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Enabled some disabled impeller fragment shader dart tests (#180759)" (flutter/flutter#180785)
2026-01-09 [email protected] Merge `widget_tester_leaks_free_test.dart` into `widget_tester_test.dart` (flutter/flutter#180600)
2026-01-09 [email protected] fix: there are no riscv fuchsia artifacts (flutter/flutter#180779)
2026-01-09 [email protected] Roll Skia from 7386219151e6 to b2b109f0e980 (1 revision) (flutter/flutter#180771)
2026-01-09 [email protected] Re-prioritize pipeline compile jobs and perform them eagerly instead of waiting. (flutter/flutter#180022)
2026-01-09 [email protected] Enabled some disabled impeller fragment shader dart tests (flutter/flutter#180759)
2026-01-09 [email protected] Roll Fuchsia Linux SDK from rxeg-6UB678HKJ4UQ... to 83Favz_zzMzdVuOHg... (flutter/flutter#180765)
2026-01-09 [email protected] [A11y ] Add `clearSemantics`in table (flutter/flutter#180665)
2026-01-09 [email protected] Update CODEOWNERS to remove chinmaygarde. (flutter/flutter#180703)
2026-01-09 [email protected] [ Tool ] Add support for linux riscv64 architecture (flutter/flutter#178711)
2026-01-09 [email protected] Roll Skia from e9b3264ade0c to 7386219151e6 (12 revisions) (flutter/flutter#180754)
2026-01-09 [email protected] Roll Dart SDK from fe2ba2c5dd50 to d25ad331b7ea (10 revisions) (flutter/flutter#180741)
2026-01-09 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Unpin google_mobile_ads (#180573)" (flutter/flutter#180761)
2026-01-09 [email protected] Fix typo in dropdown_menu.dart (flutter/flutter#180172)
2026-01-09 [email protected] Roll Packages from 039a026 to 51fe1d9 (1 revision) (flutter/flutter#180742)
2026-01-09 [email protected] Unpin google_mobile_ads (flutter/flutter#180573)
2026-01-09 [email protected] Update flutter changelog for 3.38.6 (flutter/flutter#180708)
2026-01-08 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Fix iOS xattr removal to clear all extended attributes (#180355)" (flutter/flutter#180709)
2026-01-08 [email protected] Make sure that an EditableText doesn't crash in 0x0 environment (flutter/flutter#180457)
2026-01-08 [email protected] Implementation of tooltip windows for win32 (flutter/flutter#179147)
2026-01-08 [email protected] [web] Don't serve files outside of project (flutter/flutter#180699)
2026-01-08 [email protected] Roll Skia from 837be28dd218 to e9b3264ade0c (1 revision) (flutter/flutter#180702)
2026-01-08 [email protected] Add new motion accessibility features to iOS. (flutter/flutter#178102)
2026-01-08 [email protected] Fix iOS xattr removal to clear all extended attributes (flutter/flutter#180355)
2026-01-08 [email protected] [ Widget Preview ] Move widget_preview_scaffold tests to `dev/integration_tests/widget_preview_scaffold` (flutter/flutter#180658)
2026-01-08 [email protected] De-interleaves engine dart test output (flutter/flutter#180651)
2026-01-08 [email protected] [web] Fix SemanticsService.announce not working inside dialogs (flutter/flutter#179958)
2026-01-08 [email protected] Roll Skia from 42233226ac56 to 837be28dd218 (2 revisions) (flutter/flutter#180693)
2026-01-08 [email protected] Roll Dart SDK to 3.11.0-296.2.beta (flutter/flutter#180685)
2026-01-08 [email protected] Improve code quality in `AndroidTouchProcessorTest.java` (flutter/flutter#180583)
2026-01-08 [email protected] Revert "Reverts "[reland] Unify canvas creation and Surface code in S…kwasm and CanvasKit (#179473)" (#180152)" (flutter/flutter#180610)
2026-01-08 [email protected] Roll Skia from a0c407bce408 to 42233226ac56 (4 revisions) (flutter/flutter#180688)
2026-01-08 [email protected] [ Tool ] Fix flake in overall_experience_test.dart (flutter/flutter#180655)
2026-01-08 [email protected] Roll Packages from 9705815 to 039a026 (6 revisions) (flutter/flutter#180684)
2026-01-08 [email protected] flutter_tools: Auto-generate ExportOptions.plist for manual iOS code signing (flutter/flutter#177888)
2026-01-08 [email protected] Roll Skia from 58837e160874 to a0c407bce408 (2 revisions) (flutter/flutter#180679)
2026-01-08 [email protected] Roll Skia from 1e3266fdba86 to 58837e160874 (1 revision) (flutter/flutter#180677)
2026-01-08 [email protected] Roll Skia from 3c47ea10638f to 1e3266fdba86 (4 revisions) (flutter/flutter#180675)
2026-01-08 [email protected] Roll Fuchsia Linux SDK from dTvN_JVSCfGFRasvH... to rxeg-6UB678HKJ4UQ... (flutter/flutter#180673)
...
ivan-vanyusho pushed a commit to ivan-vanyusho/packages that referenced this pull request Jan 26, 2026
Roll Flutter from 01d37bc to 73769a2 (65 revisions)

flutter/flutter@01d37bc...73769a2

2026-01-10 [email protected] Roll Dart SDK from 5e855c2bb3ef to 87fbfd5381b6 (1 revision) (flutter/flutter#180800)
2026-01-10 [email protected] Roll Skia from b2b109f0e980 to f39cc645b1dd (2 revisions) (flutter/flutter#180796)
2026-01-10 [email protected] Roll Dart SDK from b7963905e6a2 to 5e855c2bb3ef (2 revisions) (flutter/flutter#180794)
2026-01-10 [email protected] Make sure that a CupertinoTabScaffold doesn't crash in 0x0 environment (flutter/flutter#179824)
2026-01-10 [email protected] Roll Dart SDK from d25ad331b7ea to b7963905e6a2 (2 revisions) (flutter/flutter#180783)
2026-01-10 [email protected] Make sure that a Container doesn't crash in 0x0 environment (flutter/flutter#180350)
2026-01-10 [email protected] Make sure that an Expansible doesn't crash in 0x0 environment (flutter/flutter#180478)
2026-01-10 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Enabled some disabled impeller fragment shader dart tests (#180759)" (flutter/flutter#180785)
2026-01-09 [email protected] Merge `widget_tester_leaks_free_test.dart` into `widget_tester_test.dart` (flutter/flutter#180600)
2026-01-09 [email protected] fix: there are no riscv fuchsia artifacts (flutter/flutter#180779)
2026-01-09 [email protected] Roll Skia from 7386219151e6 to b2b109f0e980 (1 revision) (flutter/flutter#180771)
2026-01-09 [email protected] Re-prioritize pipeline compile jobs and perform them eagerly instead of waiting. (flutter/flutter#180022)
2026-01-09 [email protected] Enabled some disabled impeller fragment shader dart tests (flutter/flutter#180759)
2026-01-09 [email protected] Roll Fuchsia Linux SDK from rxeg-6UB678HKJ4UQ... to 83Favz_zzMzdVuOHg... (flutter/flutter#180765)
2026-01-09 [email protected] [A11y ] Add `clearSemantics`in table (flutter/flutter#180665)
2026-01-09 [email protected] Update CODEOWNERS to remove chinmaygarde. (flutter/flutter#180703)
2026-01-09 [email protected] [ Tool ] Add support for linux riscv64 architecture (flutter/flutter#178711)
2026-01-09 [email protected] Roll Skia from e9b3264ade0c to 7386219151e6 (12 revisions) (flutter/flutter#180754)
2026-01-09 [email protected] Roll Dart SDK from fe2ba2c5dd50 to d25ad331b7ea (10 revisions) (flutter/flutter#180741)
2026-01-09 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Unpin google_mobile_ads (#180573)" (flutter/flutter#180761)
2026-01-09 [email protected] Fix typo in dropdown_menu.dart (flutter/flutter#180172)
2026-01-09 [email protected] Roll Packages from 039a026 to 51fe1d9 (1 revision) (flutter/flutter#180742)
2026-01-09 [email protected] Unpin google_mobile_ads (flutter/flutter#180573)
2026-01-09 [email protected] Update flutter changelog for 3.38.6 (flutter/flutter#180708)
2026-01-08 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Fix iOS xattr removal to clear all extended attributes (#180355)" (flutter/flutter#180709)
2026-01-08 [email protected] Make sure that an EditableText doesn't crash in 0x0 environment (flutter/flutter#180457)
2026-01-08 [email protected] Implementation of tooltip windows for win32 (flutter/flutter#179147)
2026-01-08 [email protected] [web] Don't serve files outside of project (flutter/flutter#180699)
2026-01-08 [email protected] Roll Skia from 837be28dd218 to e9b3264ade0c (1 revision) (flutter/flutter#180702)
2026-01-08 [email protected] Add new motion accessibility features to iOS. (flutter/flutter#178102)
2026-01-08 [email protected] Fix iOS xattr removal to clear all extended attributes (flutter/flutter#180355)
2026-01-08 [email protected] [ Widget Preview ] Move widget_preview_scaffold tests to `dev/integration_tests/widget_preview_scaffold` (flutter/flutter#180658)
2026-01-08 [email protected] De-interleaves engine dart test output (flutter/flutter#180651)
2026-01-08 [email protected] [web] Fix SemanticsService.announce not working inside dialogs (flutter/flutter#179958)
2026-01-08 [email protected] Roll Skia from 42233226ac56 to 837be28dd218 (2 revisions) (flutter/flutter#180693)
2026-01-08 [email protected] Roll Dart SDK to 3.11.0-296.2.beta (flutter/flutter#180685)
2026-01-08 [email protected] Improve code quality in `AndroidTouchProcessorTest.java` (flutter/flutter#180583)
2026-01-08 [email protected] Revert "Reverts "[reland] Unify canvas creation and Surface code in S…kwasm and CanvasKit (#179473)" (#180152)" (flutter/flutter#180610)
2026-01-08 [email protected] Roll Skia from a0c407bce408 to 42233226ac56 (4 revisions) (flutter/flutter#180688)
2026-01-08 [email protected] [ Tool ] Fix flake in overall_experience_test.dart (flutter/flutter#180655)
2026-01-08 [email protected] Roll Packages from 9705815 to 039a026 (6 revisions) (flutter/flutter#180684)
2026-01-08 [email protected] flutter_tools: Auto-generate ExportOptions.plist for manual iOS code signing (flutter/flutter#177888)
2026-01-08 [email protected] Roll Skia from 58837e160874 to a0c407bce408 (2 revisions) (flutter/flutter#180679)
2026-01-08 [email protected] Roll Skia from 1e3266fdba86 to 58837e160874 (1 revision) (flutter/flutter#180677)
2026-01-08 [email protected] Roll Skia from 3c47ea10638f to 1e3266fdba86 (4 revisions) (flutter/flutter#180675)
2026-01-08 [email protected] Roll Fuchsia Linux SDK from dTvN_JVSCfGFRasvH... to rxeg-6UB678HKJ4UQ... (flutter/flutter#180673)
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: accessibility Accessibility, e.g. VoiceOver or TalkBack. (aka a11y) a: tests "flutter test", flutter_test, or one of our tests engine flutter/engine related. See also e: labels. framework flutter/packages/flutter repository. See also f: labels. platform-android Android applications specifically platform-ios iOS applications specifically platform-web Web applications specifically team-android Owned by Android platform team team-ios Owned by iOS platform team triaged-web Triaged by Web platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose iOS "Customize onscreen motion" accessibility settings

9 participants