// 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. import 'package:flutter/animation.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import '../flutter_test_alternative.dart'; import 'rendering_tester.dart'; void main() { test('RenderSliverOpacity does not composite if it is transparent', () { final RenderSliverOpacity renderSliverOpacity = RenderSliverOpacity( opacity: 0.0, sliver: RenderSliverToBoxAdapter( child: RenderSizedBox(const Size(1.0, 1.0)), // size doesn't matter ) ); final RenderViewport root = RenderViewport( axisDirection: AxisDirection.down, crossAxisDirection: AxisDirection.right, offset: ViewportOffset.zero(), cacheExtent: 250.0, children: <RenderSliver>[renderSliverOpacity], ); layout(root, phase: EnginePhase.composite); expect(renderSliverOpacity.needsCompositing, false); }); test('RenderSliverOpacity does not composite if it is opaque', () { final RenderSliverOpacity renderSliverOpacity = RenderSliverOpacity( opacity: 1.0, sliver: RenderSliverToBoxAdapter( child: RenderSizedBox(const Size(1.0, 1.0)), // size doesn't matter ) ); final RenderViewport root = RenderViewport( axisDirection: AxisDirection.down, crossAxisDirection: AxisDirection.right, offset: ViewportOffset.zero(), cacheExtent: 250.0, children: <RenderSliver>[renderSliverOpacity], ); layout(root, phase: EnginePhase.composite); expect(renderSliverOpacity.needsCompositing, false); }); test('RenderSliverOpacity reuses its layer', () { final RenderSliverOpacity renderSliverOpacity = RenderSliverOpacity( opacity: 0.5, sliver: RenderSliverToBoxAdapter( child: RenderSizedBox(const Size(1.0, 1.0)), // size doesn't matter ) ); final RenderViewport root = RenderViewport( axisDirection: AxisDirection.down, crossAxisDirection: AxisDirection.right, offset: ViewportOffset.zero(), cacheExtent: 250.0, children: <RenderSliver>[renderSliverOpacity] ); expect(renderSliverOpacity.debugLayer, null); layout(root, phase: EnginePhase.paint, constraints: BoxConstraints.tight(const Size(10, 10))); final ContainerLayer layer = renderSliverOpacity.debugLayer!; expect(layer, isNotNull); // Mark for repaint otherwise pumpFrame is a noop. renderSliverOpacity.markNeedsPaint(); expect(renderSliverOpacity.debugNeedsPaint, true); pumpFrame(phase: EnginePhase.paint); expect(renderSliverOpacity.debugNeedsPaint, false); expect(renderSliverOpacity.debugLayer, same(layer)); }); test('RenderSliverAnimatedOpacity does not composite if it is transparent', () async { final Animation<double> opacityAnimation = AnimationController( vsync: FakeTickerProvider(), )..value = 0.0; final RenderSliverAnimatedOpacity renderSliverAnimatedOpacity = RenderSliverAnimatedOpacity( alwaysIncludeSemantics: false, opacity: opacityAnimation, sliver: RenderSliverToBoxAdapter( child: RenderSizedBox(const Size(1.0, 1.0)), // size doesn't matter ) ); final RenderViewport root = RenderViewport( axisDirection: AxisDirection.down, crossAxisDirection: AxisDirection.right, offset: ViewportOffset.zero(), cacheExtent: 250.0, children: <RenderSliver>[renderSliverAnimatedOpacity], ); layout(root, phase: EnginePhase.composite); expect(renderSliverAnimatedOpacity.needsCompositing, false); }); test('RenderSliverAnimatedOpacity does not composite if it is opaque', () { final Animation<double> opacityAnimation = AnimationController( vsync: FakeTickerProvider(), )..value = 1.0; final RenderSliverAnimatedOpacity renderSliverAnimatedOpacity = RenderSliverAnimatedOpacity( alwaysIncludeSemantics: false, opacity: opacityAnimation, sliver: RenderSliverToBoxAdapter( child: RenderSizedBox(const Size(1.0, 1.0)), // size doesn't matter ) ); final RenderViewport root = RenderViewport( axisDirection: AxisDirection.down, crossAxisDirection: AxisDirection.right, offset: ViewportOffset.zero(), cacheExtent: 250.0, children: <RenderSliver>[renderSliverAnimatedOpacity], ); layout(root, phase: EnginePhase.composite); expect(renderSliverAnimatedOpacity.needsCompositing, false); }); test('RenderSliverAnimatedOpacity reuses its layer', () { final Animation<double> opacityAnimation = AnimationController( vsync: FakeTickerProvider(), )..value = 0.5; // must not be 0 or 1.0. Otherwise, it won't create a layer final RenderSliverAnimatedOpacity renderSliverAnimatedOpacity = RenderSliverAnimatedOpacity( opacity: opacityAnimation, sliver: RenderSliverToBoxAdapter( child: RenderSizedBox(const Size(1.0, 1.0)), // size doesn't matter ) ); final RenderViewport root = RenderViewport( axisDirection: AxisDirection.down, crossAxisDirection: AxisDirection.right, offset: ViewportOffset.zero(), cacheExtent: 250.0, children: <RenderSliver>[renderSliverAnimatedOpacity] ); expect(renderSliverAnimatedOpacity.debugLayer, null); layout(root, phase: EnginePhase.paint, constraints: BoxConstraints.tight(const Size(10, 10))); final ContainerLayer layer = renderSliverAnimatedOpacity.debugLayer!; expect(layer, isNotNull); // Mark for repaint otherwise pumpFrame is a noop. renderSliverAnimatedOpacity.markNeedsPaint(); expect(renderSliverAnimatedOpacity.debugNeedsPaint, true); pumpFrame(phase: EnginePhase.paint); expect(renderSliverAnimatedOpacity.debugNeedsPaint, false); expect(renderSliverAnimatedOpacity.debugLayer, same(layer)); }); }