Unverified Commit 908de76c authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

Remove value listener from semantics bindings (#21296)

parent 976cffa2
......@@ -14,5 +14,6 @@
library semantics;
export 'src/semantics/binding.dart';
export 'src/semantics/debug.dart';
export 'src/semantics/semantics.dart';
export 'src/semantics/semantics_service.dart';
......@@ -401,7 +401,7 @@ class AnimationController extends Animation<double>
TickerFuture _animateToInternal(double target, { Duration duration, Curve curve = Curves.linear, AnimationBehavior animationBehavior }) {
final AnimationBehavior behavior = animationBehavior ?? this.animationBehavior;
double scale = 1.0;
if (_ticker.disableAnimations) {
if (SemanticsBinding.instance.disableAnimations) {
switch (behavior) {
case AnimationBehavior.normal:
// Since the framework cannot handle zero duration animations, we run it at 5% of the normal
......@@ -496,7 +496,7 @@ class AnimationController extends Animation<double>
: upperBound + _kFlingTolerance.distance;
double scale = 1.0;
final AnimationBehavior behavior = animationBehavior ?? this.animationBehavior;
if (_ticker.disableAnimations) {
if (SemanticsBinding.instance.disableAnimations) {
switch (behavior) {
case AnimationBehavior.normal:
// TODO(jonahwilliams): determine a better process for setting velocity.
......
......@@ -68,12 +68,6 @@ class Ticker {
TickerFuture _future;
/// Whether or not the platform is requesting that animations be disabled.
///
/// See also:
/// * [AccessibilityFeatures.disableAnimations], for the setting this value comes from.
bool disableAnimations = false;
/// Whether this ticker has been silenced.
///
/// While silenced, a ticker's clock can still run, but the callback will not
......@@ -279,7 +273,6 @@ class Ticker {
assert(_startTime == null);
assert(_animationId == null);
assert((originalTicker._future == null) == (originalTicker._startTime == null), 'Cannot absorb Ticker after it has been disposed.');
disableAnimations = originalTicker.disableAnimations;
if (originalTicker._future != null) {
_future = originalTicker._future;
_startTime = originalTicker._startTime;
......
......@@ -6,6 +6,8 @@ import 'dart:ui' as ui show AccessibilityFeatures, window;
import 'package:flutter/foundation.dart';
import 'debug.dart';
export 'dart:ui' show AccessibilityFeatures;
/// The glue between the semantics layer and the Flutter engine.
......@@ -23,7 +25,7 @@ class SemanticsBinding extends BindingBase {
void initInstances() {
super.initInstances();
_instance = this;
_accessibilityFeatures = new ValueNotifier<ui.AccessibilityFeatures>(ui.window.accessibilityFeatures);
_accessibilityFeatures = ui.window.accessibilityFeatures;
}
/// Called when the platform accessibility features change.
......@@ -31,7 +33,7 @@ class SemanticsBinding extends BindingBase {
/// See [Window.onAccessibilityFeaturesChanged].
@protected
void handleAccessibilityFeaturesChanged() {
_accessibilityFeatures.value = ui.window.accessibilityFeatures;
_accessibilityFeatures = ui.window.accessibilityFeatures;
}
/// The currently active set of [AccessibilityFeatures].
......@@ -41,6 +43,20 @@ class SemanticsBinding extends BindingBase {
///
/// To listen to changes to accessibility features, create a
/// [WidgetsBindingObserver] and listen to [didChangeAccessibilityFeatures].
ValueListenable<ui.AccessibilityFeatures> get accessibilityFeatures => _accessibilityFeatures;
ValueNotifier<ui.AccessibilityFeatures> _accessibilityFeatures;
ui.AccessibilityFeatures get accessibilityFeatures => _accessibilityFeatures;
ui.AccessibilityFeatures _accessibilityFeatures;
/// The platform is requesting that animations be disabled or simplified.
///
/// This setting can be overriden for testing or debugging by setting
/// [debugSemanticsDisableAnimations].
bool get disableAnimations {
bool value = _accessibilityFeatures.disableAnimations;
assert(() {
if (debugSemanticsDisableAnimations != null)
value = debugSemanticsDisableAnimations;
return true;
}());
return value;
}
}
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// Overrides the setting of [SemanticsBinding.disableAnimations] for debugging
/// and testing.
///
/// This value is ignored in non-debug builds.
bool debugSemanticsDisableAnimations;
......@@ -4,7 +4,6 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/semantics.dart';
import 'framework.dart';
......@@ -95,10 +94,7 @@ abstract class SingleTickerProviderStateMixin<T extends StatefulWidget> extends
'mixing in a SingleTickerProviderStateMixin, use a regular TickerProviderStateMixin.'
);
}());
final ValueListenable<AccessibilityFeatures> accessibilityFeatures = SemanticsBinding.instance.accessibilityFeatures;
_ticker = new Ticker(onTick, debugLabel: 'created by $this')
..disableAnimations = accessibilityFeatures.value.disableAnimations;
accessibilityFeatures.addListener(_handleAccessibilityFeaturesChanged);
_ticker = new Ticker(onTick, debugLabel: 'created by $this');
// We assume that this is called from initState, build, or some sort of
// event handler, and that thus TickerMode.of(context) would return true. We
// can't actually check that here because if we're in initState then we're
......@@ -121,8 +117,6 @@ abstract class SingleTickerProviderStateMixin<T extends StatefulWidget> extends
'The offending ticker was: ${_ticker.toString(debugIncludeStack: true)}'
);
}());
final ValueListenable<AccessibilityFeatures> accessibilityFeatures = SemanticsBinding.instance.accessibilityFeatures;
accessibilityFeatures.removeListener(_handleAccessibilityFeaturesChanged);
super.dispose();
}
......@@ -149,13 +143,6 @@ abstract class SingleTickerProviderStateMixin<T extends StatefulWidget> extends
}
properties.add(new DiagnosticsProperty<Ticker>('ticker', _ticker, description: tickerDescription, showSeparator: false, defaultValue: null));
}
void _handleAccessibilityFeaturesChanged() {
final ValueListenable<AccessibilityFeatures> accessibilityFeatures = SemanticsBinding.instance.accessibilityFeatures;
if (_ticker != null) {
_ticker.disableAnimations = accessibilityFeatures.value.disableAnimations;
}
}
}
/// Provides [Ticker] objects that are configured to only tick while the current
......@@ -179,11 +166,8 @@ abstract class TickerProviderStateMixin<T extends StatefulWidget> extends State<
@override
Ticker createTicker(TickerCallback onTick) {
_tickers ??= new Set<_WidgetTicker>();
final ValueListenable<AccessibilityFeatures> accessibilityFeatures = SemanticsBinding.instance.accessibilityFeatures;
final _WidgetTicker result = new _WidgetTicker(onTick, this, debugLabel: 'created by $this')
..disableAnimations = accessibilityFeatures.value.disableAnimations;
final _WidgetTicker result = new _WidgetTicker(onTick, this, debugLabel: 'created by $this');
_tickers.add(result);
accessibilityFeatures.addListener(_handleAccessibilityFeaturesChanged);
return result;
}
......@@ -213,8 +197,6 @@ abstract class TickerProviderStateMixin<T extends StatefulWidget> extends State<
}
return true;
}());
final ValueListenable<AccessibilityFeatures> accessibilityFeatures = SemanticsBinding.instance.accessibilityFeatures;
accessibilityFeatures.removeListener(_handleAccessibilityFeaturesChanged);
super.dispose();
}
......@@ -241,15 +223,6 @@ abstract class TickerProviderStateMixin<T extends StatefulWidget> extends State<
defaultValue: null,
));
}
void _handleAccessibilityFeaturesChanged() {
final ValueListenable<AccessibilityFeatures> accessibilityFeatures = SemanticsBinding.instance.accessibilityFeatures;
if (_tickers != null) {
for (Ticker ticker in _tickers) {
ticker.disableAnimations = accessibilityFeatures.value.disableAnimations;
}
}
}
}
// This class should really be called _DisposingTicker or some such, but this
......
......@@ -4,6 +4,7 @@
import 'dart:ui' as ui;
import 'package:flutter/semantics.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/animation.dart';
import 'package:flutter/scheduler.dart';
......@@ -581,16 +582,17 @@ void main() {
group('AnimationBehavior', () {
test('Default values for constructor', () {
final AnimationController controller = new AnimationController(vsync: const TestVSync(disableAnimations: true));
final AnimationController controller = new AnimationController(vsync: const TestVSync());
expect(controller.animationBehavior, AnimationBehavior.normal);
final AnimationController repeating = new AnimationController.unbounded(vsync: const TestVSync(disableAnimations: true));
final AnimationController repeating = new AnimationController.unbounded(vsync: const TestVSync());
expect(repeating.animationBehavior, AnimationBehavior.preserve);
});
test('AnimationBehavior.preserve runs at normal speed when animatingTo', () async {
debugSemanticsDisableAnimations = true;
final AnimationController controller = new AnimationController(
vsync: const TestVSync(disableAnimations: true),
vsync: const TestVSync(),
animationBehavior: AnimationBehavior.preserve,
);
......@@ -609,11 +611,13 @@ void main() {
expect(controller.value, 1.0);
expect(controller.status, AnimationStatus.completed);
debugSemanticsDisableAnimations = false;
});
test('AnimationBehavior.normal runs at 20x speed when animatingTo', () async {
debugSemanticsDisableAnimations = true;
final AnimationController controller = new AnimationController(
vsync: const TestVSync(disableAnimations: true),
vsync: const TestVSync(),
animationBehavior: AnimationBehavior.normal,
);
......@@ -632,14 +636,16 @@ void main() {
expect(controller.value, 1.0);
expect(controller.status, AnimationStatus.completed);
debugSemanticsDisableAnimations = null;
});
test('AnimationBehavior.normal runs "faster" whan AnimationBehavior.preserve', () {
debugSemanticsDisableAnimations = true;
final AnimationController controller = new AnimationController(
vsync: const TestVSync(disableAnimations: true),
vsync: const TestVSync(),
);
final AnimationController fastController = new AnimationController(
vsync: const TestVSync(disableAnimations: true),
vsync: const TestVSync(),
);
controller.fling(velocity: 1.0, animationBehavior: AnimationBehavior.preserve);
......@@ -649,6 +655,7 @@ void main() {
// We don't assert a specific faction that normal animation.
expect(controller.value < fastController.value, true);
debugSemanticsDisableAnimations = null;
});
});
}
......@@ -273,9 +273,6 @@ class _FakeTicker implements Ticker {
@override
bool get shouldScheduleTick => null;
@override
bool disableAnimations = false;
@override
void dispose() {}
......
......@@ -10,16 +10,8 @@ import 'package:flutter/scheduler.dart';
/// tree.
class TestVSync implements TickerProvider {
/// Creates a ticker provider that creates standalone tickers.
const TestVSync({this.disableAnimations = false});
/// Whether to disable the animations of tickers create from this picker.
///
/// See also:
///
/// * [AccessibilityFeatures.disableAnimations], for the setting that controls this flag.
/// * [AnimationBehavior], for how animation controllers change when created from tickers with this flag.
final bool disableAnimations;
const TestVSync();
@override
Ticker createTicker(TickerCallback onTick) => new Ticker(onTick)..disableAnimations = disableAnimations;
Ticker createTicker(TickerCallback onTick) => new Ticker(onTick);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment