mirror of
https://github.com/flutter/flutter
synced 2024-09-13 05:11:45 +00:00
remove opacity layer at fully opaque (#106351)
This commit is contained in:
parent
10fb7b486d
commit
c12b0de004
|
@ -887,6 +887,7 @@ class RenderOpacity extends RenderProxyBox {
|
|||
|
||||
@override
|
||||
OffsetLayer updateCompositedLayer({required covariant OpacityLayer? oldLayer}) {
|
||||
assert(_alpha != 255);
|
||||
final OpacityLayer updatedLayer = oldLayer ?? OpacityLayer();
|
||||
updatedLayer.alpha = _alpha;
|
||||
return updatedLayer;
|
||||
|
@ -1060,7 +1061,7 @@ mixin RenderAnimatedOpacityMixin<T extends RenderObject> on RenderObjectWithChil
|
|||
_alpha = ui.Color.getAlphaFromOpacity(opacity.value);
|
||||
if (oldAlpha != _alpha) {
|
||||
final bool? wasRepaintBoundary = _currentlyIsRepaintBoundary;
|
||||
_currentlyIsRepaintBoundary = _alpha! > 0;
|
||||
_currentlyIsRepaintBoundary = _alpha! > 0 && _alpha! < 255;
|
||||
if (child != null && wasRepaintBoundary != _currentlyIsRepaintBoundary) {
|
||||
markNeedsCompositingBitsUpdate();
|
||||
}
|
||||
|
|
|
@ -272,7 +272,7 @@ void main() {
|
|||
expect(renderAnimatedOpacity.needsCompositing, false);
|
||||
});
|
||||
|
||||
test('RenderAnimatedOpacity does composite if it is opaque', () {
|
||||
test('RenderAnimatedOpacity does not composite if it is opaque', () {
|
||||
final Animation<double> opacityAnimation = AnimationController(
|
||||
vsync: FakeTickerProvider(),
|
||||
)..value = 1.0;
|
||||
|
@ -282,6 +282,20 @@ void main() {
|
|||
child: RenderSizedBox(const Size(1.0, 1.0)), // size doesn't matter
|
||||
);
|
||||
|
||||
layout(renderAnimatedOpacity, phase: EnginePhase.composite);
|
||||
expect(renderAnimatedOpacity.needsCompositing, false);
|
||||
});
|
||||
|
||||
test('RenderAnimatedOpacity does composite if it is partially opaque', () {
|
||||
final Animation<double> opacityAnimation = AnimationController(
|
||||
vsync: FakeTickerProvider(),
|
||||
)..value = 0.5;
|
||||
|
||||
final RenderAnimatedOpacity renderAnimatedOpacity = RenderAnimatedOpacity(
|
||||
opacity: opacityAnimation,
|
||||
child: RenderSizedBox(const Size(1.0, 1.0)), // size doesn't matter
|
||||
);
|
||||
|
||||
layout(renderAnimatedOpacity, phase: EnginePhase.composite);
|
||||
expect(renderAnimatedOpacity.needsCompositing, true);
|
||||
});
|
||||
|
|
|
@ -98,7 +98,30 @@ void main() {
|
|||
expect(renderSliverAnimatedOpacity.needsCompositing, false);
|
||||
});
|
||||
|
||||
test('RenderSliverAnimatedOpacity does composite if it is opaque', () {
|
||||
test('RenderSliverAnimatedOpacity does composite if it is partially opaque', () {
|
||||
final Animation<double> opacityAnimation = AnimationController(
|
||||
vsync: FakeTickerProvider(),
|
||||
)..value = 0.5;
|
||||
|
||||
final RenderSliverAnimatedOpacity renderSliverAnimatedOpacity = RenderSliverAnimatedOpacity(
|
||||
opacity: opacityAnimation,
|
||||
sliver: RenderSliverToBoxAdapter(
|
||||
child: RenderSizedBox(const Size(1.0, 1.0)), // size doesn't matter
|
||||
),
|
||||
);
|
||||
|
||||
final RenderViewport root = RenderViewport(
|
||||
crossAxisDirection: AxisDirection.right,
|
||||
offset: ViewportOffset.zero(),
|
||||
cacheExtent: 250.0,
|
||||
children: <RenderSliver>[renderSliverAnimatedOpacity],
|
||||
);
|
||||
|
||||
layout(root, phase: EnginePhase.composite);
|
||||
expect(renderSliverAnimatedOpacity.needsCompositing, true);
|
||||
});
|
||||
|
||||
test('RenderSliverAnimatedOpacity does not composite if it is opaque', () {
|
||||
final Animation<double> opacityAnimation = AnimationController(
|
||||
vsync: FakeTickerProvider(),
|
||||
)..value = 1.0;
|
||||
|
@ -118,7 +141,7 @@ void main() {
|
|||
);
|
||||
|
||||
layout(root, phase: EnginePhase.composite);
|
||||
expect(renderSliverAnimatedOpacity.needsCompositing, true);
|
||||
expect(renderSliverAnimatedOpacity.needsCompositing, false);
|
||||
});
|
||||
|
||||
test('RenderSliverAnimatedOpacity reuses its layer', () {
|
||||
|
|
|
@ -7,7 +7,7 @@ import 'package:flutter/rendering.dart';
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('RenderAnimatedOpacityMixin avoids repainting child as it animates', (WidgetTester tester) async {
|
||||
testWidgets('RenderAnimatedOpacityMixin drops layer when animating to 1', (WidgetTester tester) async {
|
||||
RenderTestObject.paintCount = 0;
|
||||
final AnimationController controller = AnimationController(vsync: const TestVSync(), duration: const Duration(seconds: 1));
|
||||
final Tween<double> opacityTween = Tween<double>(begin: 0, end: 1);
|
||||
|
@ -32,6 +32,39 @@ void main() {
|
|||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 500));
|
||||
|
||||
expect(RenderTestObject.paintCount, 2);
|
||||
|
||||
controller.stop();
|
||||
await tester.pump();
|
||||
|
||||
expect(RenderTestObject.paintCount, 2);
|
||||
});
|
||||
|
||||
testWidgets('RenderAnimatedOpacityMixin avoids repainting child as it animates', (WidgetTester tester) async {
|
||||
RenderTestObject.paintCount = 0;
|
||||
final AnimationController controller = AnimationController(vsync: const TestVSync(), duration: const Duration(seconds: 1));
|
||||
final Tween<double> opacityTween = Tween<double>(begin: 0, end: 0.99); // Layer is dropped at 1
|
||||
await tester.pumpWidget(
|
||||
Container(
|
||||
color: Colors.red,
|
||||
child: FadeTransition(
|
||||
opacity: controller.drive(opacityTween),
|
||||
child: const TestWidget(),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
expect(RenderTestObject.paintCount, 0);
|
||||
controller.forward();
|
||||
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 500));
|
||||
|
||||
expect(RenderTestObject.paintCount, 1);
|
||||
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 500));
|
||||
|
||||
expect(RenderTestObject.paintCount, 1);
|
||||
|
||||
controller.stop();
|
||||
|
@ -43,7 +76,7 @@ void main() {
|
|||
testWidgets('RenderAnimatedOpacityMixin allows opacity layer to be disposed when animating to 0 opacity', (WidgetTester tester) async {
|
||||
RenderTestObject.paintCount = 0;
|
||||
final AnimationController controller = AnimationController(vsync: const TestVSync(), duration: const Duration(seconds: 1));
|
||||
final Tween<double> opacityTween = Tween<double>(begin: 1, end: 0);
|
||||
final Tween<double> opacityTween = Tween<double>(begin: 0.99, end: 0);
|
||||
await tester.pumpWidget(
|
||||
Container(
|
||||
color: Colors.red,
|
||||
|
|
Loading…
Reference in a new issue