Kate Lovett 9d96df2364
Modernize framework lints (#179089)
WIP

Commits separated as follows:
- Update lints in analysis_options files
- Run `dart fix --apply`
- Clean up leftover analysis issues 
- Run `dart format .` in the right places.

Local analysis and testing passes. Checking CI now.

Part of https://github.com/flutter/flutter/issues/178827
- Adoption of flutter_lints in examples/api coming in a separate change
(cc @loic-sharma)

## Pre-launch Checklist

- [ ] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [ ] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [ ] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [ ] I signed the [CLA].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [ ] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [ ] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [ ] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
2025-11-26 01:10:39 +00:00

239 lines
7.8 KiB
Dart

// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// @docImport 'package:flutter/services.dart';
/// @docImport 'package:flutter/widgets.dart';
library;
import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart';
export 'dart:ui' show TextDirection;
/// Determines the assertiveness level of the accessibility announcement.
///
/// It is used by [AnnounceSemanticsEvent] to determine the priority with which
/// assistive technology should treat announcements.
enum Assertiveness {
/// The assistive technology will speak changes whenever the user is idle.
polite,
/// The assistive technology will interrupt any announcement that it is
/// currently making to notify the user about the change.
///
/// It should only be used for time-sensitive/critical notifications.
assertive,
}
/// An event sent by the application to notify interested listeners that
/// something happened to the user interface (e.g. a view scrolled).
///
/// These events are usually interpreted by assistive technologies to give the
/// user additional clues about the current state of the UI.
abstract class SemanticsEvent {
/// Initializes internal fields.
///
/// [type] is a string that identifies this class of [SemanticsEvent]s.
const SemanticsEvent(this.type);
/// The type of this event.
///
/// The type is used by the engine to translate this event into the
/// appropriate native event (`UIAccessibility*Notification` on iOS and
/// `AccessibilityEvent` on Android).
final String type;
/// Converts this event to a Map that can be encoded with
/// [StandardMessageCodec].
///
/// [nodeId] is the unique identifier of the semantics node associated with
/// the event, or null if the event is not associated with a semantics node.
Map<String, dynamic> toMap({int? nodeId}) {
final event = <String, dynamic>{'type': type, 'data': getDataMap()};
if (nodeId != null) {
event['nodeId'] = nodeId;
}
return event;
}
/// Returns the event's data object.
Map<String, dynamic> getDataMap();
@override
String toString() {
final pairs = <String>[];
final Map<String, dynamic> dataMap = getDataMap();
final List<String> sortedKeys = dataMap.keys.toList()..sort();
for (final key in sortedKeys) {
pairs.add('$key: ${dataMap[key]}');
}
return '${objectRuntimeType(this, 'SemanticsEvent')}(${pairs.join(', ')})';
}
}
/// An event for a semantic announcement.
///
/// This should be used for announcement that are not seamlessly announced by
/// the system as a result of a UI state change.
///
/// For example a camera application can use this method to make accessibility
/// announcements regarding objects in the viewfinder.
///
/// When possible, prefer using mechanisms like [Semantics] to implicitly
/// trigger announcements over using this event.
///
/// ### Android
/// Android has [deprecated announcement events][1] due to its disruptive
/// behavior with TalkBack forcing it to clear its speech queue and speak the
/// provided text. Instead, use mechanisms like [Semantics] to implicitly
/// trigger announcements.
///
/// [1]: https://developer.android.com/reference/android/view/View#announceForAccessibility(java.lang.CharSequence)
///
class AnnounceSemanticsEvent extends SemanticsEvent {
/// Constructs an event that triggers an announcement by the platform
/// for the provided view.
const AnnounceSemanticsEvent(
this.message,
this.textDirection,
this.viewId, {
this.assertiveness = Assertiveness.polite,
}) : super('announce');
/// The view that this announcement is on.
final int viewId;
/// The message to announce.
final String message;
/// Text direction for [message].
final TextDirection textDirection;
/// Determines whether the announcement should interrupt any existing announcement,
/// or queue after it.
///
/// On the web this option uses the aria-live level to set the assertiveness
/// of the announcement. On iOS, Android, Windows, Linux, macOS, and Fuchsia
/// this option currently has no effect.
final Assertiveness assertiveness;
@override
Map<String, dynamic> getDataMap() {
return <String, dynamic>{
'viewId': viewId,
'message': message,
'textDirection': textDirection.index,
if (assertiveness != Assertiveness.polite) 'assertiveness': assertiveness.index,
};
}
}
/// An event for a semantic announcement of a tooltip.
///
/// This is only used by Android to announce tooltip values.
class TooltipSemanticsEvent extends SemanticsEvent {
/// Constructs an event that triggers a tooltip announcement by the platform.
const TooltipSemanticsEvent(this.message) : super('tooltip');
/// The text content of the tooltip.
final String message;
@override
Map<String, dynamic> getDataMap() {
return <String, dynamic>{'message': message};
}
}
/// An event which triggers long press semantic feedback.
///
/// Currently only honored on Android. Triggers a long-press specific sound
/// when TalkBack is enabled.
class LongPressSemanticsEvent extends SemanticsEvent {
/// Constructs an event that triggers a long-press semantic feedback by the platform.
const LongPressSemanticsEvent() : super('longPress');
@override
Map<String, dynamic> getDataMap() => const <String, dynamic>{};
}
/// An event which triggers tap semantic feedback.
///
/// Currently only honored on Android. Triggers a tap specific sound when
/// TalkBack is enabled.
class TapSemanticEvent extends SemanticsEvent {
/// Constructs an event that triggers a long-press semantic feedback by the platform.
const TapSemanticEvent() : super('tap');
@override
Map<String, dynamic> getDataMap() => const <String, dynamic>{};
}
/// An event to move the accessibility focus.
///
/// Using this API is generally not recommended, as it may break a users' expectation of
/// how a11y focus works and therefore should be used very carefully.
///
/// One possible use case:
/// For example, the currently focused rendering object is replaced by another rendering
/// object. In general, such design should be avoided if possible. If not, one may want
/// to refocus the newly added rendering object.
///
/// One example that is not recommended:
/// When a new popup or dropdown opens, moving the focus in these cases may confuse users
/// and make it less accessible.
///
/// {@tool snippet}
///
/// The following code snippet shows how one can request focus on a
/// certain widget.
///
/// ```dart
/// class MyWidget extends StatefulWidget {
/// const MyWidget({super.key});
///
/// @override
/// State<MyWidget> createState() => _MyWidgetState();
/// }
///
/// class _MyWidgetState extends State<MyWidget> {
/// final GlobalKey mykey = GlobalKey();
///
/// @override
/// void initState() {
/// super.initState();
/// // Using addPostFrameCallback because changing focus need to wait for the widget to finish rendering.
/// WidgetsBinding.instance.addPostFrameCallback((_) {
/// mykey.currentContext?.findRenderObject()?.sendSemanticsEvent(const FocusSemanticEvent());
/// });
/// }
///
/// @override
/// Widget build(BuildContext context) {
/// return Scaffold(
/// appBar: AppBar(
/// title: const Text('example'),
/// ),
/// body: Column(
/// children: <Widget>[
/// const Text('Hello World'),
/// const SizedBox(height: 50),
/// Text('set focus here', key: mykey),
/// ],
/// ),
/// );
/// }
/// }
/// ```
/// {@end-tool}
///
/// This currently only supports Android and iOS.
class FocusSemanticEvent extends SemanticsEvent {
/// Constructs an event that triggers a focus change by the platform.
const FocusSemanticEvent() : super('focus');
@override
Map<String, dynamic> getDataMap() => const <String, dynamic>{};
}