[framework] ensure ink sparkle is disposed (#104569)
This commit is contained in:
@@ -135,7 +135,9 @@ class InkSparkle extends InteractiveInkFeature {
|
||||
_animationController = AnimationController(
|
||||
duration: _animationDuration,
|
||||
vsync: controller.vsync,
|
||||
)..addListener(controller.markNeedsPaint)..forward();
|
||||
)..addListener(controller.markNeedsPaint)
|
||||
..addStatusListener(_handleStatusChanged)
|
||||
..forward();
|
||||
|
||||
_radiusScale = TweenSequence<double>(
|
||||
<TweenSequenceItem<double>>[
|
||||
@@ -209,6 +211,11 @@ class InkSparkle extends InteractiveInkFeature {
|
||||
_turbulenceSeed = turbulenceSeed ?? math.Random().nextDouble() * 1000.0;
|
||||
}
|
||||
|
||||
void _handleStatusChanged(AnimationStatus status) {
|
||||
if (status == AnimationStatus.completed)
|
||||
dispose();
|
||||
}
|
||||
|
||||
static const Duration _animationDuration = Duration(milliseconds: 617);
|
||||
static const double _targetRadiusMultiplier = 2.3;
|
||||
static const double _rotateRight = math.pi * 0.0078125;
|
||||
@@ -259,6 +266,8 @@ class InkSparkle extends InteractiveInkFeature {
|
||||
|
||||
@override
|
||||
void paintFeature(Canvas canvas, Matrix4 transform) {
|
||||
assert(_animationController.isAnimating);
|
||||
|
||||
// InkSparkle can only paint if its shader has been compiled.
|
||||
if (_InkSparkleFactory._shaderManager == null) {
|
||||
// Skipping paintFeature because the shader it relies on is not ready to
|
||||
|
||||
@@ -557,6 +557,12 @@ class _RenderInkFeatures extends RenderProxyBox implements MaterialInkController
|
||||
|
||||
bool absorbHitTest;
|
||||
|
||||
@visibleForTesting
|
||||
List<InkFeature>? get debugInkFeatures {
|
||||
if (kDebugMode)
|
||||
return _inkFeatures;
|
||||
return null;
|
||||
}
|
||||
List<InkFeature>? _inkFeatures;
|
||||
|
||||
@override
|
||||
|
||||
@@ -48,16 +48,23 @@ void main() {
|
||||
final Finder buttonFinder = find.text('Sparkle!');
|
||||
await tester.tap(buttonFinder);
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.pump(const Duration(milliseconds: 200));
|
||||
|
||||
final MaterialInkController material = Material.of(tester.element(buttonFinder))!;
|
||||
await tester.pump(const Duration(milliseconds: 200));
|
||||
expect(material, paintsExactlyCountTimes(#drawRect, 1));
|
||||
|
||||
// ignore: avoid_dynamic_calls
|
||||
expect((material as dynamic).debugInkFeatures, hasLength(1));
|
||||
|
||||
await tester.pumpAndSettle();
|
||||
// ink feature is disposed.
|
||||
// ignore: avoid_dynamic_calls
|
||||
expect((material as dynamic).debugInkFeatures, isEmpty);
|
||||
},
|
||||
skip: kIsWeb, // [intended] SPIR-V shaders are not yet supported for web.
|
||||
);
|
||||
|
||||
testWidgets('InkSparkle default splashFactory paints with drawPaint when unbounded', (WidgetTester tester) async {
|
||||
testWidgets('InkSparkle default splashFactory paints with drawPaint when unbounded', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Center(
|
||||
@@ -72,10 +79,9 @@ void main() {
|
||||
final Finder buttonFinder = find.text('Sparkle!');
|
||||
await tester.tap(buttonFinder);
|
||||
await tester.pump();
|
||||
await tester.pumpAndSettle();
|
||||
await tester.pump(const Duration(milliseconds: 200));
|
||||
|
||||
final MaterialInkController material = Material.of(tester.element(buttonFinder))!;
|
||||
await tester.pump(const Duration(milliseconds: 200));
|
||||
expect(material, paintsExactlyCountTimes(#drawPaint, 1));
|
||||
},
|
||||
skip: kIsWeb, // [intended] SPIR-V shaders are not yet supported for web.
|
||||
|
||||
Reference in New Issue
Block a user