Add RTL support to AnimatedContainer (#11910)
Also, fix the interpolation between visual and directional fractional offsets. The interpolation now works visually in whatever direction the result eventually gets resolved into. Fixes #11847 Fixes #11357
This commit is contained in:
parent
74b0bf6480
commit
baf3b45e0d
@ -752,10 +752,10 @@ class EdgeInsetsDirectional extends EdgeInsetsGeometry {
|
|||||||
EdgeInsets resolve(TextDirection direction) {
|
EdgeInsets resolve(TextDirection direction) {
|
||||||
assert(direction != null);
|
assert(direction != null);
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case TextDirection.ltr:
|
|
||||||
return new EdgeInsets.fromLTRB(start, top, end, bottom);
|
|
||||||
case TextDirection.rtl:
|
case TextDirection.rtl:
|
||||||
return new EdgeInsets.fromLTRB(end, top, start, bottom);
|
return new EdgeInsets.fromLTRB(end, top, start, bottom);
|
||||||
|
case TextDirection.ltr:
|
||||||
|
return new EdgeInsets.fromLTRB(start, top, end, bottom);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -856,10 +856,10 @@ class _MixedEdgeInsets extends EdgeInsetsGeometry {
|
|||||||
EdgeInsets resolve(TextDirection direction) {
|
EdgeInsets resolve(TextDirection direction) {
|
||||||
assert(direction != null);
|
assert(direction != null);
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
|
case TextDirection.rtl:
|
||||||
|
return new EdgeInsets.fromLTRB(_end + _left, _top, _start + _right, _bottom);
|
||||||
case TextDirection.ltr:
|
case TextDirection.ltr:
|
||||||
return new EdgeInsets.fromLTRB(_start + _left, _top, _end + _right, _bottom);
|
return new EdgeInsets.fromLTRB(_start + _left, _top, _end + _right, _bottom);
|
||||||
case TextDirection.rtl:
|
|
||||||
return new EdgeInsets.fromLTRB(_end + _left, _top, _start + _left, _bottom);
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,12 @@ abstract class FractionalOffsetGeometry {
|
|||||||
/// const constructors so that they can be used in const expressions.
|
/// const constructors so that they can be used in const expressions.
|
||||||
const FractionalOffsetGeometry();
|
const FractionalOffsetGeometry();
|
||||||
|
|
||||||
double get _dx;
|
/// The [FractionalOffset.dx] to which this object will [resolve] in [TextDirection.ltr].
|
||||||
double get _start;
|
double get _dxForRTL;
|
||||||
|
|
||||||
|
/// The [FractionalOffset.dx] to which this object will [resolve] in [TextDirection.ltr].
|
||||||
|
double get _dxForLTR;
|
||||||
|
|
||||||
double get _dy;
|
double get _dy;
|
||||||
|
|
||||||
/// Returns the difference between two [FractionalOffsetGeometry] objects.
|
/// Returns the difference between two [FractionalOffsetGeometry] objects.
|
||||||
@ -42,9 +46,9 @@ abstract class FractionalOffsetGeometry {
|
|||||||
/// negating the argument (using the prefix unary `-` operator or multiplying
|
/// negating the argument (using the prefix unary `-` operator or multiplying
|
||||||
/// the argument by -1.0 using the `*` operator).
|
/// the argument by -1.0 using the `*` operator).
|
||||||
FractionalOffsetGeometry subtract(FractionalOffsetGeometry other) {
|
FractionalOffsetGeometry subtract(FractionalOffsetGeometry other) {
|
||||||
return new _MixedFractionalOffset(
|
return new _SchrodingersFractionalOffset(
|
||||||
_dx - other._dx,
|
_dxForRTL - other._dxForRTL,
|
||||||
_start - other._start,
|
_dxForLTR - other._dxForLTR,
|
||||||
_dy - other._dy,
|
_dy - other._dy,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -61,9 +65,9 @@ abstract class FractionalOffsetGeometry {
|
|||||||
/// representing a combination of both is returned. That object can be turned
|
/// representing a combination of both is returned. That object can be turned
|
||||||
/// into a concrete [FractionalOffset] using [resolve].
|
/// into a concrete [FractionalOffset] using [resolve].
|
||||||
FractionalOffsetGeometry add(FractionalOffsetGeometry other) {
|
FractionalOffsetGeometry add(FractionalOffsetGeometry other) {
|
||||||
return new _MixedFractionalOffset(
|
return new _SchrodingersFractionalOffset(
|
||||||
_dx + other._dx,
|
_dxForRTL + other._dxForRTL,
|
||||||
_start + other._start,
|
_dxForLTR + other._dxForLTR,
|
||||||
_dy + other._dy,
|
_dy + other._dy,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -113,22 +117,22 @@ abstract class FractionalOffsetGeometry {
|
|||||||
if ((a == null || a is FractionalOffsetDirectional) && (b == null || b is FractionalOffsetDirectional))
|
if ((a == null || a is FractionalOffsetDirectional) && (b == null || b is FractionalOffsetDirectional))
|
||||||
return FractionalOffsetDirectional.lerp(a, b, t);
|
return FractionalOffsetDirectional.lerp(a, b, t);
|
||||||
if (a == null) {
|
if (a == null) {
|
||||||
return new _MixedFractionalOffset(
|
return new _SchrodingersFractionalOffset(
|
||||||
ui.lerpDouble(0.5, b._dx, t),
|
ui.lerpDouble(0.5, b._dxForRTL, t),
|
||||||
ui.lerpDouble(0.0, b._start, t),
|
ui.lerpDouble(0.5, b._dxForLTR, t),
|
||||||
ui.lerpDouble(0.5, b._dy, t),
|
ui.lerpDouble(0.5, b._dy, t),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (b == null) {
|
if (b == null) {
|
||||||
return new _MixedFractionalOffset(
|
return new _SchrodingersFractionalOffset(
|
||||||
ui.lerpDouble(a._dx, 0.5, t),
|
ui.lerpDouble(a._dxForRTL, 0.5, t),
|
||||||
ui.lerpDouble(a._start, 0.0, t),
|
ui.lerpDouble(a._dxForLTR, 0.5, t),
|
||||||
ui.lerpDouble(a._dy, 0.5, t),
|
ui.lerpDouble(a._dy, 0.5, t),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return new _MixedFractionalOffset(
|
return new _SchrodingersFractionalOffset(
|
||||||
ui.lerpDouble(a._dx, b._dx, t),
|
ui.lerpDouble(a._dxForRTL, b._dxForRTL, t),
|
||||||
ui.lerpDouble(a._start, b._start, t),
|
ui.lerpDouble(a._dxForLTR, b._dxForLTR, t),
|
||||||
ui.lerpDouble(a._dy, b._dy, t),
|
ui.lerpDouble(a._dy, b._dy, t),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -142,62 +146,15 @@ abstract class FractionalOffsetGeometry {
|
|||||||
/// * [FractionalOffset], for which this is a no-op (returns itself).
|
/// * [FractionalOffset], for which this is a no-op (returns itself).
|
||||||
/// * [FractionalOffsetDirectional], which flips the horizontal direction
|
/// * [FractionalOffsetDirectional], which flips the horizontal direction
|
||||||
/// based on the `direction` argument.
|
/// based on the `direction` argument.
|
||||||
FractionalOffset resolve(TextDirection direction);
|
FractionalOffset resolve(TextDirection direction) {
|
||||||
|
assert(direction != null);
|
||||||
@override
|
switch (direction) {
|
||||||
String toString() {
|
case TextDirection.rtl:
|
||||||
double x = _dx;
|
return new FractionalOffset(_dxForRTL, _dy);
|
||||||
double start = _start;
|
case TextDirection.ltr:
|
||||||
if (this is FractionalOffset) {
|
return new FractionalOffset(_dxForLTR, _dy);
|
||||||
assert(start == 0.0);
|
|
||||||
start = null;
|
|
||||||
} else if (start == 0.5) {
|
|
||||||
x += 0.5;
|
|
||||||
start = null;
|
|
||||||
}
|
}
|
||||||
if (start == null) {
|
return null;
|
||||||
if (x == 0.0 && _dy == 0.0)
|
|
||||||
return 'FractionalOffset.topLeft';
|
|
||||||
if (x == 0.5 && _dy == 0.0)
|
|
||||||
return 'FractionalOffset.topCenter';
|
|
||||||
if (x == 1.0 && _dy == 0.0)
|
|
||||||
return 'FractionalOffset.topRight';
|
|
||||||
if (x == 0.0 && _dy == 0.5)
|
|
||||||
return 'FractionalOffset.centerLeft';
|
|
||||||
if (x == 0.5 && _dy == 0.5)
|
|
||||||
return 'FractionalOffset.center';
|
|
||||||
if (x == 1.0 && _dy == 0.5)
|
|
||||||
return 'FractionalOffset.centerRight';
|
|
||||||
if (x == 0.0 && _dy == 1.0)
|
|
||||||
return 'FractionalOffset.bottomLeft';
|
|
||||||
if (x == 0.5 && _dy == 1.0)
|
|
||||||
return 'FractionalOffset.bottomCenter';
|
|
||||||
if (x == 1.0 && _dy == 1.0)
|
|
||||||
return 'FractionalOffset.bottomRight';
|
|
||||||
return 'FractionalOffset(${x.toStringAsFixed(1)}, '
|
|
||||||
'${_dy.toStringAsFixed(1)})';
|
|
||||||
} else if (x == 0.0) {
|
|
||||||
assert(start != 0.5);
|
|
||||||
if (start == 0.0 && _dy == 0.0)
|
|
||||||
return 'FractionalOffsetDirectional.topStart';
|
|
||||||
if (start == 1.0 && _dy == 0.0)
|
|
||||||
return 'FractionalOffsetDirectional.topEnd';
|
|
||||||
if (start == 0.0 && _dy == 0.5)
|
|
||||||
return 'FractionalOffsetDirectional.centerStart';
|
|
||||||
if (start == 1.0 && _dy == 0.5)
|
|
||||||
return 'FractionalOffsetDirectional.centerEnd';
|
|
||||||
if (start == 0.0 && _dy == 1.0)
|
|
||||||
return 'FractionalOffsetDirectional.bottomStart';
|
|
||||||
if (start == 1.0 && _dy == 1.0)
|
|
||||||
return 'FractionalOffsetDirectional.bottomEnd';
|
|
||||||
return 'FractionalOffsetDirectional(${start.toStringAsFixed(1)}, '
|
|
||||||
'${_dy.toStringAsFixed(1)})';
|
|
||||||
}
|
|
||||||
return 'FractionalOffset(${_dx.toStringAsFixed(1)}, '
|
|
||||||
'${_dy.toStringAsFixed(1)})'
|
|
||||||
' + '
|
|
||||||
'FractionalOffsetDirectional(${_start.toStringAsFixed(1)}, '
|
|
||||||
'0.0)';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -205,13 +162,13 @@ abstract class FractionalOffsetGeometry {
|
|||||||
if (other is! FractionalOffsetGeometry)
|
if (other is! FractionalOffsetGeometry)
|
||||||
return false;
|
return false;
|
||||||
final FractionalOffsetGeometry typedOther = other;
|
final FractionalOffsetGeometry typedOther = other;
|
||||||
return _dx == typedOther._dx &&
|
return _dxForRTL == typedOther._dxForRTL &&
|
||||||
_start == typedOther._start &&
|
_dxForLTR == typedOther._dxForLTR &&
|
||||||
_dy == typedOther._dy;
|
_dy == typedOther._dy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => hashValues(_dx, _start, _dy);
|
int get hashCode => hashValues(_dxForRTL, _dxForLTR, _dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An offset that's expressed as a fraction of a [Size].
|
/// An offset that's expressed as a fraction of a [Size].
|
||||||
@ -279,7 +236,10 @@ class FractionalOffset extends FractionalOffsetGeometry {
|
|||||||
final double dx;
|
final double dx;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
double get _dx => dx;
|
double get _dxForRTL => dx;
|
||||||
|
|
||||||
|
@override
|
||||||
|
double get _dxForLTR => dx;
|
||||||
|
|
||||||
/// The distance fraction in the vertical direction.
|
/// The distance fraction in the vertical direction.
|
||||||
///
|
///
|
||||||
@ -292,9 +252,6 @@ class FractionalOffset extends FractionalOffsetGeometry {
|
|||||||
@override
|
@override
|
||||||
double get _dy => dy;
|
double get _dy => dy;
|
||||||
|
|
||||||
@override
|
|
||||||
double get _start => 0.0;
|
|
||||||
|
|
||||||
/// The top left corner.
|
/// The top left corner.
|
||||||
static const FractionalOffset topLeft = const FractionalOffset(0.0, 0.0);
|
static const FractionalOffset topLeft = const FractionalOffset(0.0, 0.0);
|
||||||
|
|
||||||
@ -420,6 +377,32 @@ class FractionalOffset extends FractionalOffsetGeometry {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
FractionalOffset resolve(TextDirection direction) => this;
|
FractionalOffset resolve(TextDirection direction) => this;
|
||||||
|
|
||||||
|
static String _stringify(double dx, double dy) {
|
||||||
|
if (dx == 0.0 && dy == 0.0)
|
||||||
|
return 'FractionalOffset.topLeft';
|
||||||
|
if (dx == 0.5 && dy == 0.0)
|
||||||
|
return 'FractionalOffset.topCenter';
|
||||||
|
if (dx == 1.0 && dy == 0.0)
|
||||||
|
return 'FractionalOffset.topRight';
|
||||||
|
if (dx == 0.0 && dy == 0.5)
|
||||||
|
return 'FractionalOffset.centerLeft';
|
||||||
|
if (dx == 0.5 && dy == 0.5)
|
||||||
|
return 'FractionalOffset.center';
|
||||||
|
if (dx == 1.0 && dy == 0.5)
|
||||||
|
return 'FractionalOffset.centerRight';
|
||||||
|
if (dx == 0.0 && dy == 1.0)
|
||||||
|
return 'FractionalOffset.bottomLeft';
|
||||||
|
if (dx == 0.5 && dy == 1.0)
|
||||||
|
return 'FractionalOffset.bottomCenter';
|
||||||
|
if (dx == 1.0 && dy == 1.0)
|
||||||
|
return 'FractionalOffset.bottomRight';
|
||||||
|
return 'FractionalOffset(${dx.toStringAsFixed(1)}, '
|
||||||
|
'${dy.toStringAsFixed(1)})';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => _stringify(dx, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An offset that's expressed as a fraction of a [Size], but whose horizontal
|
/// An offset that's expressed as a fraction of a [Size], but whose horizontal
|
||||||
@ -455,7 +438,10 @@ class FractionalOffsetDirectional extends FractionalOffsetGeometry {
|
|||||||
final double start;
|
final double start;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
double get _start => start;
|
double get _dxForRTL => 1.0 - start;
|
||||||
|
|
||||||
|
@override
|
||||||
|
double get _dxForLTR => start;
|
||||||
|
|
||||||
/// The distance fraction in the vertical direction.
|
/// The distance fraction in the vertical direction.
|
||||||
///
|
///
|
||||||
@ -471,9 +457,6 @@ class FractionalOffsetDirectional extends FractionalOffsetGeometry {
|
|||||||
@override
|
@override
|
||||||
double get _dy => dy;
|
double get _dy => dy;
|
||||||
|
|
||||||
@override
|
|
||||||
double get _dx => 0.0;
|
|
||||||
|
|
||||||
/// The top corner on the "start" side.
|
/// The top corner on the "start" side.
|
||||||
static const FractionalOffsetDirectional topStart = const FractionalOffsetDirectional(0.0, 0.0);
|
static const FractionalOffsetDirectional topStart = const FractionalOffsetDirectional(0.0, 0.0);
|
||||||
|
|
||||||
@ -578,84 +561,89 @@ class FractionalOffsetDirectional extends FractionalOffsetGeometry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FractionalOffset resolve(TextDirection direction) {
|
String toString() {
|
||||||
assert(direction != null);
|
assert(start != 0.5);
|
||||||
switch (direction) {
|
if (start == 0.0 && dy == 0.0)
|
||||||
case TextDirection.ltr:
|
return 'FractionalOffsetDirectional.topStart';
|
||||||
return new FractionalOffset(start, dy);
|
if (start == 1.0 && dy == 0.0)
|
||||||
case TextDirection.rtl:
|
return 'FractionalOffsetDirectional.topEnd';
|
||||||
return new FractionalOffset(1.0 - start, dy);
|
if (start == 0.0 && dy == 0.5)
|
||||||
}
|
return 'FractionalOffsetDirectional.centerStart';
|
||||||
return null;
|
if (start == 1.0 && dy == 0.5)
|
||||||
|
return 'FractionalOffsetDirectional.centerEnd';
|
||||||
|
if (start == 0.0 && dy == 1.0)
|
||||||
|
return 'FractionalOffsetDirectional.bottomStart';
|
||||||
|
if (start == 1.0 && dy == 1.0)
|
||||||
|
return 'FractionalOffsetDirectional.bottomEnd';
|
||||||
|
return 'FractionalOffsetDirectional(${start.toStringAsFixed(1)}, '
|
||||||
|
'${dy.toStringAsFixed(1)})';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MixedFractionalOffset extends FractionalOffsetGeometry {
|
class _SchrodingersFractionalOffset extends FractionalOffsetGeometry {
|
||||||
const _MixedFractionalOffset(this._dx, this._start, this._dy);
|
const _SchrodingersFractionalOffset(this._dxForRTL, this._dxForLTR, this._dy);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final double _dx;
|
final double _dxForRTL;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final double _start;
|
final double _dxForLTR;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final double _dy;
|
final double _dy;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MixedFractionalOffset operator -() {
|
_SchrodingersFractionalOffset operator -() {
|
||||||
return new _MixedFractionalOffset(
|
return new _SchrodingersFractionalOffset(
|
||||||
-_dx,
|
-_dxForRTL,
|
||||||
-_start,
|
-_dxForLTR,
|
||||||
-_dy,
|
-_dy,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MixedFractionalOffset operator *(double other) {
|
_SchrodingersFractionalOffset operator *(double other) {
|
||||||
return new _MixedFractionalOffset(
|
return new _SchrodingersFractionalOffset(
|
||||||
_dx * other,
|
_dxForRTL * other,
|
||||||
_start * other,
|
_dxForLTR * other,
|
||||||
_dy * other,
|
_dy * other,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MixedFractionalOffset operator /(double other) {
|
_SchrodingersFractionalOffset operator /(double other) {
|
||||||
return new _MixedFractionalOffset(
|
return new _SchrodingersFractionalOffset(
|
||||||
_dx / other,
|
_dxForRTL / other,
|
||||||
_start / other,
|
_dxForLTR / other,
|
||||||
_dy / other,
|
_dy / other,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MixedFractionalOffset operator ~/(double other) {
|
_SchrodingersFractionalOffset operator ~/(double other) {
|
||||||
return new _MixedFractionalOffset(
|
return new _SchrodingersFractionalOffset(
|
||||||
(_dx ~/ other).toDouble(),
|
(_dxForRTL ~/ other).toDouble(),
|
||||||
(_start ~/ other).toDouble(),
|
(_dxForLTR ~/ other).toDouble(),
|
||||||
(_dy ~/ other).toDouble(),
|
(_dy ~/ other).toDouble(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_MixedFractionalOffset operator %(double other) {
|
_SchrodingersFractionalOffset operator %(double other) {
|
||||||
return new _MixedFractionalOffset(
|
return new _SchrodingersFractionalOffset(
|
||||||
_dx % other,
|
_dxForRTL % other,
|
||||||
_start % other,
|
_dxForLTR % other,
|
||||||
_dy % other,
|
_dy % other,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FractionalOffset resolve(TextDirection direction) {
|
String toString() {
|
||||||
assert(direction != null);
|
if (_dxForRTL == _dxForLTR)
|
||||||
switch (direction) {
|
return FractionalOffset._stringify(_dxForRTL, _dy);
|
||||||
case TextDirection.ltr:
|
|
||||||
return new FractionalOffset(_start + _dx, _dy);
|
return '${FractionalOffset._stringify(_dxForRTL, _dy)} in RTL'
|
||||||
case TextDirection.rtl:
|
' or '
|
||||||
return new FractionalOffset((1.0 - _start) + _dx, _dy);
|
'${FractionalOffset._stringify(_dxForLTR, _dy)} in LTR';
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,16 @@ import 'package:flutter/painting.dart';
|
|||||||
/// appropriate for rectangles.
|
/// appropriate for rectangles.
|
||||||
///
|
///
|
||||||
/// See [Tween] for a discussion on how to use interpolation objects.
|
/// See [Tween] for a discussion on how to use interpolation objects.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [FractionalOffsetGeometryTween], which interpolates between two
|
||||||
|
/// [FractionalOffsetGeometry] objects.
|
||||||
class FractionalOffsetTween extends Tween<FractionalOffset> {
|
class FractionalOffsetTween extends Tween<FractionalOffset> {
|
||||||
/// Creates a fractional offset tween.
|
/// Creates a fractional offset tween.
|
||||||
///
|
///
|
||||||
/// The [begin] and [end] properties may be null; the null value
|
/// The [begin] and [end] properties may be null; the null value
|
||||||
/// is treated as meaning the top left corner.
|
/// is treated as meaning the center.
|
||||||
FractionalOffsetTween({ FractionalOffset begin, FractionalOffset end })
|
FractionalOffsetTween({ FractionalOffset begin, FractionalOffset end })
|
||||||
: super(begin: begin, end: end);
|
: super(begin: begin, end: end);
|
||||||
|
|
||||||
@ -23,3 +28,29 @@ class FractionalOffsetTween extends Tween<FractionalOffset> {
|
|||||||
@override
|
@override
|
||||||
FractionalOffset lerp(double t) => FractionalOffset.lerp(begin, end, t);
|
FractionalOffset lerp(double t) => FractionalOffset.lerp(begin, end, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An interpolation between two [FractionalOffsetGeometry].
|
||||||
|
///
|
||||||
|
/// This class specializes the interpolation of [Tween<FractionalOffsetGeometry>]
|
||||||
|
/// to be appropriate for rectangles.
|
||||||
|
///
|
||||||
|
/// See [Tween] for a discussion on how to use interpolation objects.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [FractionalOffsetTween], which interpolates between two
|
||||||
|
/// [FractionalOffset] objects.
|
||||||
|
class FractionalOffsetGeometryTween extends Tween<FractionalOffsetGeometry> {
|
||||||
|
/// Creates a fractional offset geometry tween.
|
||||||
|
///
|
||||||
|
/// The [begin] and [end] properties may be null; the null value
|
||||||
|
/// is treated as meaning the center.
|
||||||
|
FractionalOffsetGeometryTween({
|
||||||
|
FractionalOffsetGeometry begin,
|
||||||
|
FractionalOffsetGeometry end,
|
||||||
|
}) : super(begin: begin, end: end);
|
||||||
|
|
||||||
|
/// Returns the value this variable has at the given animation clock value.
|
||||||
|
@override
|
||||||
|
FractionalOffsetGeometry lerp(double t) => FractionalOffsetGeometry.lerp(begin, end, t);
|
||||||
|
}
|
||||||
|
@ -29,6 +29,7 @@ export 'package:flutter/rendering.dart' show
|
|||||||
FlowDelegate,
|
FlowDelegate,
|
||||||
FlowPaintingContext,
|
FlowPaintingContext,
|
||||||
FractionalOffsetTween,
|
FractionalOffsetTween,
|
||||||
|
FractionalOffsetGeometryTween,
|
||||||
HitTestBehavior,
|
HitTestBehavior,
|
||||||
LayerLink,
|
LayerLink,
|
||||||
MainAxisAlignment,
|
MainAxisAlignment,
|
||||||
|
@ -61,6 +61,11 @@ class DecorationTween extends Tween<Decoration> {
|
|||||||
/// [EdgeInsets.lerp].
|
/// [EdgeInsets.lerp].
|
||||||
///
|
///
|
||||||
/// See [Tween] for a discussion on how to use interpolation objects.
|
/// See [Tween] for a discussion on how to use interpolation objects.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [EdgeInsetsGeometryTween], which interpolates between two
|
||||||
|
/// [EdgeInsetsGeometry] objects.
|
||||||
class EdgeInsetsTween extends Tween<EdgeInsets> {
|
class EdgeInsetsTween extends Tween<EdgeInsets> {
|
||||||
/// Creates an [EdgeInsets] tween.
|
/// Creates an [EdgeInsets] tween.
|
||||||
///
|
///
|
||||||
@ -73,6 +78,28 @@ class EdgeInsetsTween extends Tween<EdgeInsets> {
|
|||||||
EdgeInsets lerp(double t) => EdgeInsets.lerp(begin, end, t);
|
EdgeInsets lerp(double t) => EdgeInsets.lerp(begin, end, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An interpolation between two [EdgeInsetsGeometry]s.
|
||||||
|
///
|
||||||
|
/// This class specializes the interpolation of [Tween<EdgeInsetsGeometry>] to
|
||||||
|
/// use [EdgeInsetsGeometry.lerp].
|
||||||
|
///
|
||||||
|
/// See [Tween] for a discussion on how to use interpolation objects.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [EdgeInsetsTween], which interpolates between two [EdgeInsets] objects.
|
||||||
|
class EdgeInsetsGeometryTween extends Tween<EdgeInsetsGeometry> {
|
||||||
|
/// Creates an [EdgeInsetsGeometry] tween.
|
||||||
|
///
|
||||||
|
/// The [begin] and [end] properties may be null; the null value
|
||||||
|
/// is treated as an [EdgeInsetsGeometry] with no inset.
|
||||||
|
EdgeInsetsGeometryTween({ EdgeInsetsGeometry begin, EdgeInsetsGeometry end }) : super(begin: begin, end: end);
|
||||||
|
|
||||||
|
/// Returns the value this variable has at the given animation clock value.
|
||||||
|
@override
|
||||||
|
EdgeInsetsGeometry lerp(double t) => EdgeInsetsGeometry.lerp(begin, end, t);
|
||||||
|
}
|
||||||
|
|
||||||
/// An interpolation between two [BorderRadius]s.
|
/// An interpolation between two [BorderRadius]s.
|
||||||
///
|
///
|
||||||
/// This class specializes the interpolation of [Tween<BorderRadius>] to use
|
/// This class specializes the interpolation of [Tween<BorderRadius>] to use
|
||||||
@ -358,11 +385,11 @@ class AnimatedContainer extends ImplicitlyAnimatedWidget {
|
|||||||
/// constraints are unbounded, then the child will be shrink-wrapped instead.
|
/// constraints are unbounded, then the child will be shrink-wrapped instead.
|
||||||
///
|
///
|
||||||
/// Ignored if [child] is null.
|
/// Ignored if [child] is null.
|
||||||
final FractionalOffset alignment;
|
final FractionalOffsetGeometry alignment;
|
||||||
|
|
||||||
/// Empty space to inscribe inside the [decoration]. The [child], if any, is
|
/// Empty space to inscribe inside the [decoration]. The [child], if any, is
|
||||||
/// placed inside this padding.
|
/// placed inside this padding.
|
||||||
final EdgeInsets padding;
|
final EdgeInsetsGeometry padding;
|
||||||
|
|
||||||
/// The decoration to paint behind the [child].
|
/// The decoration to paint behind the [child].
|
||||||
///
|
///
|
||||||
@ -383,7 +410,7 @@ class AnimatedContainer extends ImplicitlyAnimatedWidget {
|
|||||||
final BoxConstraints constraints;
|
final BoxConstraints constraints;
|
||||||
|
|
||||||
/// Empty space to surround the [decoration] and [child].
|
/// Empty space to surround the [decoration] and [child].
|
||||||
final EdgeInsets margin;
|
final EdgeInsetsGeometry margin;
|
||||||
|
|
||||||
/// The transformation matrix to apply before painting the container.
|
/// The transformation matrix to apply before painting the container.
|
||||||
final Matrix4 transform;
|
final Matrix4 transform;
|
||||||
@ -394,33 +421,33 @@ class AnimatedContainer extends ImplicitlyAnimatedWidget {
|
|||||||
@override
|
@override
|
||||||
void debugFillProperties(DiagnosticPropertiesBuilder description) {
|
void debugFillProperties(DiagnosticPropertiesBuilder description) {
|
||||||
super.debugFillProperties(description);
|
super.debugFillProperties(description);
|
||||||
description.add(new DiagnosticsProperty<FractionalOffset>('alignment', alignment, showName: false, defaultValue: null));
|
description.add(new DiagnosticsProperty<FractionalOffsetGeometry>('alignment', alignment, showName: false, defaultValue: null));
|
||||||
description.add(new DiagnosticsProperty<EdgeInsets>('padding', padding, defaultValue: null));
|
description.add(new DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding, defaultValue: null));
|
||||||
description.add(new DiagnosticsProperty<Decoration>('bg', decoration, defaultValue: null));
|
description.add(new DiagnosticsProperty<Decoration>('bg', decoration, defaultValue: null));
|
||||||
description.add(new DiagnosticsProperty<Decoration>('fg', foregroundDecoration, defaultValue: null));
|
description.add(new DiagnosticsProperty<Decoration>('fg', foregroundDecoration, defaultValue: null));
|
||||||
description.add(new DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: null, showName: false));
|
description.add(new DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: null, showName: false));
|
||||||
description.add(new DiagnosticsProperty<EdgeInsets>('margin', margin, defaultValue: null));
|
description.add(new DiagnosticsProperty<EdgeInsetsGeometry>('margin', margin, defaultValue: null));
|
||||||
description.add(new ObjectFlagProperty<Matrix4>.has('transform', transform));
|
description.add(new ObjectFlagProperty<Matrix4>.has('transform', transform));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AnimatedContainerState extends AnimatedWidgetBaseState<AnimatedContainer> {
|
class _AnimatedContainerState extends AnimatedWidgetBaseState<AnimatedContainer> {
|
||||||
FractionalOffsetTween _alignment;
|
FractionalOffsetGeometryTween _alignment;
|
||||||
EdgeInsetsTween _padding;
|
EdgeInsetsGeometryTween _padding;
|
||||||
DecorationTween _decoration;
|
DecorationTween _decoration;
|
||||||
DecorationTween _foregroundDecoration;
|
DecorationTween _foregroundDecoration;
|
||||||
BoxConstraintsTween _constraints;
|
BoxConstraintsTween _constraints;
|
||||||
EdgeInsetsTween _margin;
|
EdgeInsetsGeometryTween _margin;
|
||||||
Matrix4Tween _transform;
|
Matrix4Tween _transform;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void forEachTween(TweenVisitor<dynamic> visitor) {
|
void forEachTween(TweenVisitor<dynamic> visitor) {
|
||||||
_alignment = visitor(_alignment, widget.alignment, (dynamic value) => new FractionalOffsetTween(begin: value));
|
_alignment = visitor(_alignment, widget.alignment, (dynamic value) => new FractionalOffsetGeometryTween(begin: value));
|
||||||
_padding = visitor(_padding, widget.padding, (dynamic value) => new EdgeInsetsTween(begin: value));
|
_padding = visitor(_padding, widget.padding, (dynamic value) => new EdgeInsetsGeometryTween(begin: value));
|
||||||
_decoration = visitor(_decoration, widget.decoration, (dynamic value) => new DecorationTween(begin: value));
|
_decoration = visitor(_decoration, widget.decoration, (dynamic value) => new DecorationTween(begin: value));
|
||||||
_foregroundDecoration = visitor(_foregroundDecoration, widget.foregroundDecoration, (dynamic value) => new DecorationTween(begin: value));
|
_foregroundDecoration = visitor(_foregroundDecoration, widget.foregroundDecoration, (dynamic value) => new DecorationTween(begin: value));
|
||||||
_constraints = visitor(_constraints, widget.constraints, (dynamic value) => new BoxConstraintsTween(begin: value));
|
_constraints = visitor(_constraints, widget.constraints, (dynamic value) => new BoxConstraintsTween(begin: value));
|
||||||
_margin = visitor(_margin, widget.margin, (dynamic value) => new EdgeInsetsTween(begin: value));
|
_margin = visitor(_margin, widget.margin, (dynamic value) => new EdgeInsetsGeometryTween(begin: value));
|
||||||
_transform = visitor(_transform, widget.transform, (dynamic value) => new Matrix4Tween(begin: value));
|
_transform = visitor(_transform, widget.transform, (dynamic value) => new Matrix4Tween(begin: value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,12 +468,12 @@ class _AnimatedContainerState extends AnimatedWidgetBaseState<AnimatedContainer>
|
|||||||
@override
|
@override
|
||||||
void debugFillProperties(DiagnosticPropertiesBuilder description) {
|
void debugFillProperties(DiagnosticPropertiesBuilder description) {
|
||||||
super.debugFillProperties(description);
|
super.debugFillProperties(description);
|
||||||
description.add(new DiagnosticsProperty<FractionalOffsetTween>('alignment', _alignment, showName: false, defaultValue: null));
|
description.add(new DiagnosticsProperty<FractionalOffsetGeometryTween>('alignment', _alignment, showName: false, defaultValue: null));
|
||||||
description.add(new DiagnosticsProperty<EdgeInsetsTween>('padding', _padding, defaultValue: null));
|
description.add(new DiagnosticsProperty<EdgeInsetsGeometryTween>('padding', _padding, defaultValue: null));
|
||||||
description.add(new DiagnosticsProperty<DecorationTween>('bg', _decoration, defaultValue: null));
|
description.add(new DiagnosticsProperty<DecorationTween>('bg', _decoration, defaultValue: null));
|
||||||
description.add(new DiagnosticsProperty<DecorationTween>('fg', _foregroundDecoration, defaultValue: null));
|
description.add(new DiagnosticsProperty<DecorationTween>('fg', _foregroundDecoration, defaultValue: null));
|
||||||
description.add(new DiagnosticsProperty<BoxConstraintsTween>('constraints', _constraints, showName: false, defaultValue: null));
|
description.add(new DiagnosticsProperty<BoxConstraintsTween>('constraints', _constraints, showName: false, defaultValue: null));
|
||||||
description.add(new DiagnosticsProperty<EdgeInsetsTween>('margin', _margin, defaultValue: null));
|
description.add(new DiagnosticsProperty<EdgeInsetsGeometryTween>('margin', _margin, defaultValue: null));
|
||||||
description.add(new ObjectFlagProperty<Matrix4Tween>.has('transform', _transform));
|
description.add(new ObjectFlagProperty<Matrix4Tween>.has('transform', _transform));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,15 +73,15 @@ void main() {
|
|||||||
|
|
||||||
expect(FractionalOffsetGeometry.lerp(directional1, directional2, 0.5), const FractionalOffsetDirectional(0.125 + (2.0 - 0.125) / 2.0, 0.625 + (3.0 - 0.625) / 2.0));
|
expect(FractionalOffsetGeometry.lerp(directional1, directional2, 0.5), const FractionalOffsetDirectional(0.125 + (2.0 - 0.125) / 2.0, 0.625 + (3.0 - 0.625) / 2.0));
|
||||||
expect(FractionalOffsetGeometry.lerp(directional2, directional2, 0.5), directional2);
|
expect(FractionalOffsetGeometry.lerp(directional2, directional2, 0.5), directional2);
|
||||||
expect(FractionalOffsetGeometry.lerp(directional1, normal2, 0.5).resolve(TextDirection.ltr), const FractionalOffset(1.0 + 1.0 / 16.0, 0.625 + (3.0 - 0.625) / 2.0));
|
expect(FractionalOffsetGeometry.lerp(directional1, normal2, 0.5).resolve(TextDirection.ltr), const FractionalOffset(1.0 + 1.0 / 16.0, 0.625 + (3.0 - 0.625) / 2.0));
|
||||||
expect(FractionalOffsetGeometry.lerp(directional1, normal2, 0.5).resolve(TextDirection.rtl), const FractionalOffset(1.0 + 15.0 / 16.0, 0.625 + (3.0 - 0.625) / 2.0));
|
expect(FractionalOffsetGeometry.lerp(directional1, normal2, 0.5).resolve(TextDirection.rtl), new FractionalOffset(lerpDouble(0.875, 2.0, 0.5), 0.625 + (3.0 - 0.625) / 2.0));
|
||||||
expect(FractionalOffsetGeometry.lerp(directional1, mixed1, 0.5).resolve(TextDirection.ltr), new FractionalOffset(1.0 / 32.0 + 2.5 / 16.0, lerpDouble(0.625, 0.5625 + 0.6875, 0.5)));
|
expect(FractionalOffsetGeometry.lerp(directional1, mixed1, 0.5).resolve(TextDirection.ltr), new FractionalOffset(1.0 / 32.0 + 2.5 / 16.0, lerpDouble(0.625, 0.5625 + 0.6875, 0.5)));
|
||||||
expect(FractionalOffsetGeometry.lerp(directional1, mixed1, 0.5).resolve(TextDirection.rtl), new FractionalOffset(1.0 / 32.0 + 1.0 - 2.5 / 16.0, lerpDouble(0.625, 0.5625 + 0.6875, 0.5)));
|
expect(FractionalOffsetGeometry.lerp(directional1, mixed1, 0.5).resolve(TextDirection.rtl), new FractionalOffset(1.0 / 32.0 + 1.0 - 2.5 / 16.0, lerpDouble(0.625, 0.5625 + 0.6875, 0.5)));
|
||||||
expect(FractionalOffsetGeometry.lerp(mixed1, mixed2, 0.5).resolve(TextDirection.ltr), new FractionalOffset(3.0 + 5.0 / 8.0, lerpDouble(0.5625 + 0.6875, 6.0, 0.5)));
|
expect(FractionalOffsetGeometry.lerp(mixed1, mixed2, 0.5).resolve(TextDirection.ltr), new FractionalOffset(3.0 + 5.0 / 8.0, lerpDouble(0.5625 + 0.6875, 6.0, 0.5)));
|
||||||
expect(FractionalOffsetGeometry.lerp(mixed1, mixed2, 0.5).resolve(TextDirection.rtl), new FractionalOffset(2.0 - 41.0 / 16.0, lerpDouble(0.5625 + 0.6875, 6.0, 0.5)));
|
expect(FractionalOffsetGeometry.lerp(mixed1, mixed2, 0.5).resolve(TextDirection.rtl), new FractionalOffset(2.0 - 41.0 / 16.0, lerpDouble(0.5625 + 0.6875, 6.0, 0.5)));
|
||||||
expect(FractionalOffsetGeometry.lerp(normal1, normal2, 0.5), const FractionalOffset(0.25 + (2.0 - 0.25) / 2.0, 0.875 + (3.0 - 0.875) / 2.0));
|
expect(FractionalOffsetGeometry.lerp(normal1, normal2, 0.5), const FractionalOffset(0.25 + (2.0 - 0.25) / 2.0, 0.875 + (3.0 - 0.875) / 2.0));
|
||||||
expect(FractionalOffsetGeometry.lerp(normal1, mixed1, 0.5).resolve(TextDirection.ltr), new FractionalOffset(lerpDouble(0.25, 0.0625, 0.5) + lerpDouble(0.0, 0.1875, 0.5), lerpDouble(0.875, 0.5625 + 0.6875, 0.5)));
|
expect(FractionalOffsetGeometry.lerp(normal1, mixed1, 0.5).resolve(TextDirection.ltr), new FractionalOffset(lerpDouble(0.25, 0.0625, 0.5) + lerpDouble(0.0, 0.1875, 0.5), lerpDouble(0.875, 0.5625 + 0.6875, 0.5)));
|
||||||
expect(FractionalOffsetGeometry.lerp(normal1, mixed1, 0.5).resolve(TextDirection.rtl), new FractionalOffset(lerpDouble(0.25, 0.0625, 0.5) + 1.0 - lerpDouble(0.0, 0.1875, 0.5), lerpDouble(0.875, 0.5625 + 0.6875, 0.5)));
|
expect(FractionalOffsetGeometry.lerp(normal1, mixed1, 0.5).resolve(TextDirection.rtl), new FractionalOffset(lerpDouble(0.25, 0.0625 + 0.8125, 0.5), lerpDouble(0.875, 0.5625 + 0.6875, 0.5)));
|
||||||
expect(FractionalOffsetGeometry.lerp(null, mixed1, 0.5).resolve(TextDirection.ltr), FractionalOffsetGeometry.lerp(FractionalOffset.center, mixed1, 0.5).resolve(TextDirection.ltr));
|
expect(FractionalOffsetGeometry.lerp(null, mixed1, 0.5).resolve(TextDirection.ltr), FractionalOffsetGeometry.lerp(FractionalOffset.center, mixed1, 0.5).resolve(TextDirection.ltr));
|
||||||
expect(FractionalOffsetGeometry.lerp(mixed2, null, 0.25).resolve(TextDirection.ltr), FractionalOffsetGeometry.lerp(FractionalOffset.center, mixed2, 0.75).resolve(TextDirection.ltr));
|
expect(FractionalOffsetGeometry.lerp(mixed2, null, 0.25).resolve(TextDirection.ltr), FractionalOffsetGeometry.lerp(FractionalOffset.center, mixed2, 0.75).resolve(TextDirection.ltr));
|
||||||
expect(FractionalOffsetGeometry.lerp(directional1, null, 1.0), FractionalOffsetDirectional.center);
|
expect(FractionalOffsetGeometry.lerp(directional1, null, 1.0), FractionalOffsetDirectional.center);
|
||||||
@ -98,6 +98,35 @@ void main() {
|
|||||||
expect(FractionalOffsetGeometry.lerp(mixed1, mixed2, 0.25), mixed3);
|
expect(FractionalOffsetGeometry.lerp(mixed1, mixed2, 0.25), mixed3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('lerp commutes with resolve', () {
|
||||||
|
final List<FractionalOffsetGeometry> offsets = <FractionalOffsetGeometry>[
|
||||||
|
const FractionalOffset(-1.0, 0.65),
|
||||||
|
const FractionalOffsetDirectional(-1.0, 0.45),
|
||||||
|
const FractionalOffsetDirectional(0.125, 0.625),
|
||||||
|
const FractionalOffset(0.25, 0.875),
|
||||||
|
const FractionalOffset(0.0625, 0.5625).add(const FractionalOffsetDirectional(0.1875, 0.6875)),
|
||||||
|
const FractionalOffsetDirectional(2.0, 3.0),
|
||||||
|
const FractionalOffset(2.0, 3.0),
|
||||||
|
const FractionalOffset(2.0, 3.0).add(const FractionalOffsetDirectional(5.0, 3.0)),
|
||||||
|
const FractionalOffset(10.0, 20.0).add(const FractionalOffsetDirectional(30.0, 50.0)),
|
||||||
|
const FractionalOffset(70.0, 110.0).add(const FractionalOffsetDirectional(130.0, 170.0)),
|
||||||
|
const FractionalOffset(25.0, 42.5).add(const FractionalOffsetDirectional(55.0, 80.0)),
|
||||||
|
];
|
||||||
|
|
||||||
|
final List<double> times = <double>[ 0.0, 0.25, 0.5, 0.75, 1.0 ];
|
||||||
|
|
||||||
|
for (TextDirection direction in TextDirection.values) {
|
||||||
|
for (FractionalOffsetGeometry a in offsets) {
|
||||||
|
for (FractionalOffsetGeometry b in offsets) {
|
||||||
|
for (double t in times) {
|
||||||
|
expect(FractionalOffsetGeometry.lerp(a, b, t).resolve(direction),
|
||||||
|
FractionalOffset.lerp(a.resolve(direction), b.resolve(direction), t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('FractionalOffsetGeometry add/subtract', () {
|
test('FractionalOffsetGeometry add/subtract', () {
|
||||||
final FractionalOffsetGeometry directional = const FractionalOffsetDirectional(1.0, 2.0);
|
final FractionalOffsetGeometry directional = const FractionalOffsetDirectional(1.0, 2.0);
|
||||||
final FractionalOffsetGeometry normal = const FractionalOffset(3.0, 5.0);
|
final FractionalOffsetGeometry normal = const FractionalOffset(3.0, 5.0);
|
||||||
@ -136,10 +165,10 @@ void main() {
|
|||||||
test('FractionalOffsetGeometry toString', () {
|
test('FractionalOffsetGeometry toString', () {
|
||||||
expect(const FractionalOffset(1.0001, 2.0001).toString(), 'FractionalOffset(1.0, 2.0)');
|
expect(const FractionalOffset(1.0001, 2.0001).toString(), 'FractionalOffset(1.0, 2.0)');
|
||||||
expect(const FractionalOffset(0.0, 0.0).toString(), 'FractionalOffset.topLeft');
|
expect(const FractionalOffset(0.0, 0.0).toString(), 'FractionalOffset.topLeft');
|
||||||
expect(const FractionalOffset(0.0, 1.0).add(const FractionalOffsetDirectional(1.0, 0.0)).toString(), 'FractionalOffsetDirectional.bottomEnd');
|
expect(const FractionalOffset(0.0, 1.0).add(const FractionalOffsetDirectional(1.0, 0.0)).toString(), 'FractionalOffset.bottomLeft in RTL or FractionalOffset.bottomRight in LTR');
|
||||||
expect(const FractionalOffset(0.0001, 0.0001).toString(), 'FractionalOffset(0.0, 0.0)');
|
expect(const FractionalOffset(0.0001, 0.0001).toString(), 'FractionalOffset(0.0, 0.0)');
|
||||||
expect(const FractionalOffset(0.0, 0.0).toString(), 'FractionalOffset.topLeft');
|
expect(const FractionalOffset(0.0, 0.0).toString(), 'FractionalOffset.topLeft');
|
||||||
expect(const FractionalOffsetDirectional(0.0, 0.0).toString(), 'FractionalOffsetDirectional.topStart');
|
expect(const FractionalOffsetDirectional(0.0, 0.0).toString(), 'FractionalOffsetDirectional.topStart');
|
||||||
expect(const FractionalOffset(1.0, 1.0).add(const FractionalOffsetDirectional(1.0, 1.0)).toString(), 'FractionalOffset(1.0, 2.0) + FractionalOffsetDirectional(1.0, 0.0)');
|
expect(const FractionalOffset(1.0, 1.0).add(const FractionalOffsetDirectional(1.0, 1.0)).toString(), 'FractionalOffset(1.0, 2.0) in RTL or FractionalOffset(2.0, 2.0) in LTR');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,90 @@ void main() {
|
|||||||
expect(tester.binding.transientCallbackCount, 0);
|
expect(tester.binding.transientCallbackCount, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('AnimatedContainer padding visual-to-directional animation', (WidgetTester tester) async {
|
||||||
|
final Key target = new UniqueKey();
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
new Directionality(
|
||||||
|
textDirection: TextDirection.rtl,
|
||||||
|
child: new AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
padding: const EdgeInsets.only(right: 50.0),
|
||||||
|
child: new SizedBox.expand(key: target),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tester.getSize(find.byKey(target)), const Size(750.0, 600.0));
|
||||||
|
expect(tester.getTopRight(find.byKey(target)), const Offset(750.0, 0.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
new Directionality(
|
||||||
|
textDirection: TextDirection.rtl,
|
||||||
|
child: new AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
padding: const EdgeInsetsDirectional.only(start: 100.0),
|
||||||
|
child: new SizedBox.expand(key: target),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tester.getSize(find.byKey(target)), const Size(750.0, 600.0));
|
||||||
|
expect(tester.getTopRight(find.byKey(target)), const Offset(750.0, 0.0));
|
||||||
|
|
||||||
|
await tester.pump(const Duration(milliseconds: 100));
|
||||||
|
|
||||||
|
expect(tester.getSize(find.byKey(target)), const Size(725.0, 600.0));
|
||||||
|
expect(tester.getTopRight(find.byKey(target)), const Offset(725.0, 0.0));
|
||||||
|
|
||||||
|
await tester.pump(const Duration(milliseconds: 500));
|
||||||
|
|
||||||
|
expect(tester.getSize(find.byKey(target)), const Size(700.0, 600.0));
|
||||||
|
expect(tester.getTopRight(find.byKey(target)), const Offset(700.0, 0.0));
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('AnimatedContainer alignment visual-to-directional animation', (WidgetTester tester) async {
|
||||||
|
final Key target = new UniqueKey();
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
new Directionality(
|
||||||
|
textDirection: TextDirection.rtl,
|
||||||
|
child: new AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
alignment: FractionalOffset.topRight,
|
||||||
|
child: new SizedBox(key: target, width: 100.0, height: 200.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tester.getSize(find.byKey(target)), const Size(100.0, 200.0));
|
||||||
|
expect(tester.getTopRight(find.byKey(target)), const Offset(800.0, 0.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
new Directionality(
|
||||||
|
textDirection: TextDirection.rtl,
|
||||||
|
child: new AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
alignment: FractionalOffsetDirectional.bottomStart,
|
||||||
|
child: new SizedBox(key: target, width: 100.0, height: 200.0),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tester.getSize(find.byKey(target)), const Size(100.0, 200.0));
|
||||||
|
expect(tester.getTopRight(find.byKey(target)), const Offset(800.0, 0.0));
|
||||||
|
|
||||||
|
await tester.pump(const Duration(milliseconds: 100));
|
||||||
|
|
||||||
|
expect(tester.getSize(find.byKey(target)), const Size(100.0, 200.0));
|
||||||
|
expect(tester.getTopRight(find.byKey(target)), const Offset(800.0, 200.0));
|
||||||
|
|
||||||
|
await tester.pump(const Duration(milliseconds: 500));
|
||||||
|
|
||||||
|
expect(tester.getSize(find.byKey(target)), const Size(100.0, 200.0));
|
||||||
|
expect(tester.getTopRight(find.byKey(target)), const Offset(800.0, 400.0));
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('Animation rerun', (WidgetTester tester) async {
|
testWidgets('Animation rerun', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
new Center(
|
new Center(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user