Create DecoratedBoxTransition AnimatedWidget (#9369)
This commit is contained in:
@@ -16,6 +16,10 @@ import 'image.dart';
|
||||
/// not.
|
||||
///
|
||||
/// Commonly used with [BoxDecoration].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [DecoratedBoxTransition], the version of this class that animates on the [decoration] property.
|
||||
class DecoratedBox extends SingleChildRenderObjectWidget {
|
||||
/// Creates a widget that paints a [Decoration].
|
||||
///
|
||||
|
||||
@@ -233,7 +233,8 @@ abstract class AnimatedWidgetBaseState<T extends ImplicitlyAnimatedWidget> exten
|
||||
/// This class is useful for generating simple implicit transitions between
|
||||
/// different parameters to [Container] with its internal
|
||||
/// [AnimationController]. For more complex animations, you'll likely want to
|
||||
/// use a subclass of [Transition] or use your own [AnimationController].
|
||||
/// use a subclass of [Transition] such as the [DecoratedBoxTransition] or use
|
||||
/// your own [AnimationController].
|
||||
class AnimatedContainer extends ImplicitlyAnimatedWidget {
|
||||
/// Creates a container that animates its parameters implicitly.
|
||||
///
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:vector_math/vector_math_64.dart' show Matrix4;
|
||||
|
||||
import 'basic.dart';
|
||||
import 'container.dart';
|
||||
import 'framework.dart';
|
||||
|
||||
export 'package:flutter/rendering.dart' show RelativeRect;
|
||||
@@ -388,6 +389,52 @@ class RelativePositionedTransition extends AnimatedWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// Animated version of a [DecoratedBox] that animates the different properties
|
||||
/// of its [Decoration].
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [DecoratedBox], which also draws a [Decoration] but is not animated.
|
||||
/// * [AnimatedContainer], a more full-featured container that also animates on
|
||||
/// decoration using an internal animation.
|
||||
class DecoratedBoxTransition extends AnimatedWidget {
|
||||
/// Creates an animated [DecorationBox] whose [Decoration] animation updates
|
||||
/// the widget.
|
||||
///
|
||||
/// The [decoration] and [position] cannot be null.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [new DecoratedBox].
|
||||
DecoratedBoxTransition({
|
||||
Key key,
|
||||
@required this.decoration,
|
||||
this.position: DecorationPosition.background,
|
||||
@required this.child,
|
||||
}) : super(key: key, listenable: decoration);
|
||||
|
||||
/// Animation of the decoration to paint.
|
||||
///
|
||||
/// Can be created using a [DecorationTween] interpolating typically between
|
||||
/// two [BoxDecoration].
|
||||
final Animation<Decoration> decoration;
|
||||
|
||||
/// Whether to paint the box decoration behind or in front of the child.
|
||||
final DecorationPosition position;
|
||||
|
||||
/// The widget below this widget in the tree.
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return new DecoratedBox(
|
||||
decoration: decoration.value,
|
||||
position: position,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder that builds a widget given a child.
|
||||
///
|
||||
/// The child should typically be part of the returned widget tree.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
void main() {
|
||||
@@ -13,4 +14,132 @@ void main() {
|
||||
);
|
||||
expect(widget.toString, isNot(throwsException));
|
||||
});
|
||||
|
||||
group('ContainerTransition test', () {
|
||||
final DecorationTween decorationTween = new DecorationTween(
|
||||
begin: new BoxDecoration(
|
||||
backgroundColor: const Color(0xFFFFFFFF),
|
||||
border: new Border.all(
|
||||
color: const Color(0xFF000000),
|
||||
style: BorderStyle.solid,
|
||||
width: 4.0,
|
||||
),
|
||||
borderRadius: BorderRadius.zero,
|
||||
shape: BoxShape.rectangle,
|
||||
boxShadow: const <BoxShadow> [const BoxShadow(
|
||||
color: const Color(0x66000000),
|
||||
blurRadius: 10.0,
|
||||
spreadRadius: 4.0,
|
||||
)],
|
||||
),
|
||||
end: new BoxDecoration(
|
||||
backgroundColor: const Color(0xFF000000),
|
||||
border: new Border.all(
|
||||
color: const Color(0xFF202020),
|
||||
style: BorderStyle.solid,
|
||||
width: 1.0,
|
||||
),
|
||||
borderRadius: new BorderRadius.circular(10.0),
|
||||
shape: BoxShape.rectangle,
|
||||
// No shadow.
|
||||
),
|
||||
);
|
||||
|
||||
AnimationController controller;
|
||||
|
||||
setUp(() {
|
||||
controller = new AnimationController(vsync: const TestVSync());
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'decoration test',
|
||||
(WidgetTester tester) async {
|
||||
final DecoratedBoxTransition transitionUnderTest =
|
||||
new DecoratedBoxTransition(
|
||||
decoration: decorationTween.animate(controller),
|
||||
child: const Text("Doesn't matter"),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(transitionUnderTest);
|
||||
RenderDecoratedBox actualBox =
|
||||
tester.renderObject(find.byType(DecoratedBox));
|
||||
BoxDecoration actualDecoration = actualBox.decoration;
|
||||
|
||||
expect(actualDecoration.backgroundColor, const Color(0xFFFFFFFF));
|
||||
expect(actualDecoration.boxShadow[0].blurRadius, 10.0);
|
||||
expect(actualDecoration.boxShadow[0].spreadRadius, 4.0);
|
||||
expect(actualDecoration.boxShadow[0].color, const Color(0x66000000));
|
||||
|
||||
controller.value = 0.5;
|
||||
|
||||
await tester.pump();
|
||||
actualBox = tester.renderObject(find.byType(DecoratedBox));
|
||||
actualDecoration = actualBox.decoration;
|
||||
|
||||
expect(actualDecoration.backgroundColor, const Color(0xFF7F7F7F));
|
||||
expect(actualDecoration.border.left.width, 2.5);
|
||||
expect(actualDecoration.border.left.style, BorderStyle.solid);
|
||||
expect(actualDecoration.border.left.color, const Color(0xFF101010));
|
||||
expect(actualDecoration.borderRadius, new BorderRadius.circular(5.0));
|
||||
expect(actualDecoration.shape, BoxShape.rectangle);
|
||||
expect(actualDecoration.boxShadow[0].blurRadius, 5.0);
|
||||
expect(actualDecoration.boxShadow[0].spreadRadius, 2.0);
|
||||
// Scaling a shadow doesn't change the color.
|
||||
expect(actualDecoration.boxShadow[0].color, const Color(0x66000000));
|
||||
|
||||
controller.value = 1.0;
|
||||
|
||||
await tester.pump();
|
||||
actualBox = tester.renderObject(find.byType(DecoratedBox));
|
||||
actualDecoration = actualBox.decoration;
|
||||
|
||||
expect(actualDecoration.backgroundColor, const Color(0xFF000000));
|
||||
expect(actualDecoration.boxShadow, null);
|
||||
}
|
||||
);
|
||||
|
||||
testWidgets('animations work with curves test', (WidgetTester tester) async {
|
||||
final Animation<Decoration> curvedDecorationAnimation =
|
||||
decorationTween.animate(new CurvedAnimation(
|
||||
parent: controller,
|
||||
curve: Curves.easeOut,
|
||||
));
|
||||
|
||||
final DecoratedBoxTransition transitionUnderTest =
|
||||
new DecoratedBoxTransition(
|
||||
decoration: curvedDecorationAnimation,
|
||||
position: DecorationPosition.foreground,
|
||||
child: const Text("Doesn't matter"),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(transitionUnderTest);
|
||||
RenderDecoratedBox actualBox =
|
||||
tester.renderObject(find.byType(DecoratedBox));
|
||||
BoxDecoration actualDecoration = actualBox.decoration;
|
||||
|
||||
expect(actualDecoration.backgroundColor, const Color(0xFFFFFFFF));
|
||||
expect(actualDecoration.boxShadow[0].blurRadius, 10.0);
|
||||
expect(actualDecoration.boxShadow[0].spreadRadius, 4.0);
|
||||
expect(actualDecoration.boxShadow[0].color, const Color(0x66000000));
|
||||
|
||||
controller.value = 0.5;
|
||||
|
||||
await tester.pump();
|
||||
actualBox = tester.renderObject(find.byType(DecoratedBox));
|
||||
actualDecoration = actualBox.decoration;
|
||||
|
||||
// Same as the test above but the values should be much closer to the
|
||||
// tween's end values given the easeOut curve.
|
||||
expect(actualDecoration.backgroundColor, const Color(0xFF505050));
|
||||
expect(actualDecoration.border.left.width, closeTo(1.9, 0.1));
|
||||
expect(actualDecoration.border.left.style, BorderStyle.solid);
|
||||
expect(actualDecoration.border.left.color, const Color(0xFF151515));
|
||||
expect(actualDecoration.borderRadius.topLeft.x, closeTo(6.8, 0.1));
|
||||
expect(actualDecoration.shape, BoxShape.rectangle);
|
||||
expect(actualDecoration.boxShadow[0].blurRadius, closeTo(3.1, 0.1));
|
||||
expect(actualDecoration.boxShadow[0].spreadRadius, closeTo(1.2, 0.1));
|
||||
// Scaling a shadow doesn't change the color.
|
||||
expect(actualDecoration.boxShadow[0].color, const Color(0x66000000));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user