parent
16c363ac07
commit
c4cdbf86eb
@ -1618,13 +1618,15 @@ class RenderTransform extends RenderProxyBox {
|
|||||||
RenderTransform({
|
RenderTransform({
|
||||||
@required Matrix4 transform,
|
@required Matrix4 transform,
|
||||||
Offset origin,
|
Offset origin,
|
||||||
Alignment alignment,
|
AlignmentGeometry alignment,
|
||||||
|
TextDirection textDirection,
|
||||||
this.transformHitTests: true,
|
this.transformHitTests: true,
|
||||||
RenderBox child
|
RenderBox child
|
||||||
}) : assert(transform != null),
|
}) : assert(transform != null),
|
||||||
super(child) {
|
super(child) {
|
||||||
this.transform = transform;
|
this.transform = transform;
|
||||||
this.alignment = alignment;
|
this.alignment = alignment;
|
||||||
|
this.textDirection = textDirection;
|
||||||
this.origin = origin;
|
this.origin = origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1646,16 +1648,35 @@ class RenderTransform extends RenderProxyBox {
|
|||||||
///
|
///
|
||||||
/// This is equivalent to setting an origin based on the size of the box.
|
/// This is equivalent to setting an origin based on the size of the box.
|
||||||
/// If it is specified at the same time as an offset, both are applied.
|
/// If it is specified at the same time as an offset, both are applied.
|
||||||
Alignment get alignment => _alignment;
|
///
|
||||||
Alignment _alignment;
|
/// An [AlignmentDirectional.start] value is the same as an [Alignment]
|
||||||
set alignment(Alignment value) {
|
/// whose [Alignment.x] value is `-1.0` if [textDirection] is
|
||||||
assert(value == null || (value.x != null && value.y != null));
|
/// [TextDirection.ltr], and `1.0` if [textDirection] is [TextDirection.rtl].
|
||||||
|
/// Similarly [AlignmentDirectional.end] is the same as an [Alignment]
|
||||||
|
/// whose [Alignment.x] value is `1.0` if [textDirection] is
|
||||||
|
/// [TextDirection.ltr], and `-1.0` if [textDirection] is [TextDirection.rtl].
|
||||||
|
AlignmentGeometry get alignment => _alignment;
|
||||||
|
AlignmentGeometry _alignment;
|
||||||
|
set alignment(AlignmentGeometry value) {
|
||||||
if (_alignment == value)
|
if (_alignment == value)
|
||||||
return;
|
return;
|
||||||
_alignment = value;
|
_alignment = value;
|
||||||
markNeedsPaint();
|
markNeedsPaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The text direction with which to resolve [alignment].
|
||||||
|
///
|
||||||
|
/// This may be changed to null, but only after [alignment] has been changed
|
||||||
|
/// to a value that does not depend on the direction.
|
||||||
|
TextDirection get textDirection => _textDirection;
|
||||||
|
TextDirection _textDirection;
|
||||||
|
set textDirection(TextDirection value) {
|
||||||
|
if (_textDirection == value)
|
||||||
|
return;
|
||||||
|
_textDirection = value;
|
||||||
|
markNeedsPaint();
|
||||||
|
}
|
||||||
|
|
||||||
/// When set to true, hit tests are performed based on the position of the
|
/// When set to true, hit tests are performed based on the position of the
|
||||||
/// child as it is painted. When set to false, hit tests are performed
|
/// child as it is painted. When set to false, hit tests are performed
|
||||||
/// ignoring the transformation.
|
/// ignoring the transformation.
|
||||||
@ -1713,18 +1734,19 @@ class RenderTransform extends RenderProxyBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 get _effectiveTransform {
|
Matrix4 get _effectiveTransform {
|
||||||
if (_origin == null && _alignment == null)
|
final Alignment resolvedAlignment = alignment?.resolve(textDirection);
|
||||||
|
if (_origin == null && resolvedAlignment == null)
|
||||||
return _transform;
|
return _transform;
|
||||||
final Matrix4 result = new Matrix4.identity();
|
final Matrix4 result = new Matrix4.identity();
|
||||||
if (_origin != null)
|
if (_origin != null)
|
||||||
result.translate(_origin.dx, _origin.dy);
|
result.translate(_origin.dx, _origin.dy);
|
||||||
Offset translation;
|
Offset translation;
|
||||||
if (_alignment != null) {
|
if (resolvedAlignment != null) {
|
||||||
translation = _alignment.alongSize(size);
|
translation = resolvedAlignment.alongSize(size);
|
||||||
result.translate(translation.dx, translation.dy);
|
result.translate(translation.dx, translation.dy);
|
||||||
}
|
}
|
||||||
result.multiply(_transform);
|
result.multiply(_transform);
|
||||||
if (_alignment != null)
|
if (resolvedAlignment != null)
|
||||||
result.translate(-translation.dx, -translation.dy);
|
result.translate(-translation.dx, -translation.dy);
|
||||||
if (_origin != null)
|
if (_origin != null)
|
||||||
result.translate(-_origin.dx, -_origin.dy);
|
result.translate(-_origin.dx, -_origin.dy);
|
||||||
@ -1770,6 +1792,7 @@ class RenderTransform extends RenderProxyBox {
|
|||||||
description.add(new TransformProperty('transform matrix', _transform));
|
description.add(new TransformProperty('transform matrix', _transform));
|
||||||
description.add(new DiagnosticsProperty<Offset>('origin', origin));
|
description.add(new DiagnosticsProperty<Offset>('origin', origin));
|
||||||
description.add(new DiagnosticsProperty<Alignment>('alignment', alignment));
|
description.add(new DiagnosticsProperty<Alignment>('alignment', alignment));
|
||||||
|
description.add(new EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
|
||||||
description.add(new DiagnosticsProperty<bool>('transformHitTests', transformHitTests));
|
description.add(new DiagnosticsProperty<bool>('transformHitTests', transformHitTests));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1822,7 +1845,7 @@ class RenderFittedBox extends RenderProxyBox {
|
|||||||
/// parent's bounds. An alignment of (1.0, 0.5) aligns the child to the middle
|
/// parent's bounds. An alignment of (1.0, 0.5) aligns the child to the middle
|
||||||
/// of the right edge of its parent's bounds.
|
/// of the right edge of its parent's bounds.
|
||||||
///
|
///
|
||||||
/// If this is set to a [AlignmentDirectional] object, then
|
/// If this is set to an [AlignmentDirectional] object, then
|
||||||
/// [textDirection] must not be null.
|
/// [textDirection] must not be null.
|
||||||
AlignmentGeometry get alignment => _alignment;
|
AlignmentGeometry get alignment => _alignment;
|
||||||
AlignmentGeometry _alignment;
|
AlignmentGeometry _alignment;
|
||||||
@ -1951,7 +1974,7 @@ class RenderFittedBox extends RenderProxyBox {
|
|||||||
|
|
||||||
/// Applies a translation transformation before painting its child.
|
/// Applies a translation transformation before painting its child.
|
||||||
///
|
///
|
||||||
/// The translation is expressed as a [Offset] scaled to the child's size. For
|
/// The translation is expressed as an [Offset] scaled to the child's size. For
|
||||||
/// example, an [Offset] with a `dx` of 0.25 will result in a horizontal
|
/// example, an [Offset] with a `dx` of 0.25 will result in a horizontal
|
||||||
/// translation of one quarter the width of the child.
|
/// translation of one quarter the width of the child.
|
||||||
///
|
///
|
||||||
|
@ -794,10 +794,17 @@ class Transform extends SingleChildRenderObjectWidget {
|
|||||||
/// The alignment of the origin, relative to the size of the box.
|
/// The alignment of the origin, relative to the size of the box.
|
||||||
///
|
///
|
||||||
/// This is equivalent to setting an origin based on the size of the box.
|
/// This is equivalent to setting an origin based on the size of the box.
|
||||||
/// If it is specified at the same time as an offset, both are applied.
|
/// If it is specified at the same time as the [origin], both are applied.
|
||||||
final Alignment alignment;
|
///
|
||||||
|
/// An [AlignmentDirectional.start] value is the same as an [Alignment]
|
||||||
|
/// whose [Alignment.x] value is `-1.0` if [textDirection] is
|
||||||
|
/// [TextDirection.ltr], and `1.0` if [textDirection] is [TextDirection.rtl].
|
||||||
|
/// Similarly [AlignmentDirectional.end] is the same as an [Alignment]
|
||||||
|
/// whose [Alignment.x] value is `1.0` if [textDirection] is
|
||||||
|
/// [TextDirection.ltr], and `-1.0` if [textDirection] is [TextDirection.rtl].
|
||||||
|
final AlignmentGeometry alignment;
|
||||||
|
|
||||||
/// Whether to apply the translation when performing hit tests.
|
/// Whether to apply the transformation when performing hit tests.
|
||||||
final bool transformHitTests;
|
final bool transformHitTests;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -806,6 +813,7 @@ class Transform extends SingleChildRenderObjectWidget {
|
|||||||
transform: transform,
|
transform: transform,
|
||||||
origin: origin,
|
origin: origin,
|
||||||
alignment: alignment,
|
alignment: alignment,
|
||||||
|
textDirection: Directionality.of(context),
|
||||||
transformHitTests: transformHitTests
|
transformHitTests: transformHitTests
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -816,6 +824,7 @@ class Transform extends SingleChildRenderObjectWidget {
|
|||||||
..transform = transform
|
..transform = transform
|
||||||
..origin = origin
|
..origin = origin
|
||||||
..alignment = alignment
|
..alignment = alignment
|
||||||
|
..textDirection = Directionality.of(context)
|
||||||
..transformHitTests = transformHitTests;
|
..transformHitTests = transformHitTests;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1195,7 +1204,7 @@ class Padding extends SingleChildRenderObjectWidget {
|
|||||||
/// * [Center], which is the same as [Align] but with the [alignment] always
|
/// * [Center], which is the same as [Align] but with the [alignment] always
|
||||||
/// set to [Alignment.center].
|
/// set to [Alignment.center].
|
||||||
/// * [FractionallySizedBox], which sizes its child based on a fraction of its own
|
/// * [FractionallySizedBox], which sizes its child based on a fraction of its own
|
||||||
/// size and positions the child according to a [Alignment] value.
|
/// size and positions the child according to an [Alignment] value.
|
||||||
class Align extends SingleChildRenderObjectWidget {
|
class Align extends SingleChildRenderObjectWidget {
|
||||||
/// Creates an alignment widget.
|
/// Creates an alignment widget.
|
||||||
///
|
///
|
||||||
@ -1291,9 +1300,9 @@ class Center extends Align {
|
|||||||
///
|
///
|
||||||
/// * [SingleChildLayoutDelegate], which controls the layout of the child.
|
/// * [SingleChildLayoutDelegate], which controls the layout of the child.
|
||||||
/// * [Align], which sizes itself based on its child's size and positions
|
/// * [Align], which sizes itself based on its child's size and positions
|
||||||
/// the child according to a [Alignment] value.
|
/// the child according to an [Alignment] value.
|
||||||
/// * [FractionallySizedBox], which sizes its child based on a fraction of its own
|
/// * [FractionallySizedBox], which sizes its child based on a fraction of its own
|
||||||
/// size and positions the child according to a [Alignment] value.
|
/// size and positions the child according to an [Alignment] value.
|
||||||
/// * [CustomMultiChildLayout], which uses a delegate to position multiple
|
/// * [CustomMultiChildLayout], which uses a delegate to position multiple
|
||||||
/// children.
|
/// children.
|
||||||
class CustomSingleChildLayout extends SingleChildRenderObjectWidget {
|
class CustomSingleChildLayout extends SingleChildRenderObjectWidget {
|
||||||
@ -1568,7 +1577,7 @@ class ConstrainedBox extends SingleChildRenderObjectWidget {
|
|||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [Align] (which sizes itself based on its child's size and positions
|
/// * [Align] (which sizes itself based on its child's size and positions
|
||||||
/// the child according to a [Alignment] value)
|
/// the child according to an [Alignment] value)
|
||||||
/// * [OverflowBox]
|
/// * [OverflowBox]
|
||||||
class FractionallySizedBox extends SingleChildRenderObjectWidget {
|
class FractionallySizedBox extends SingleChildRenderObjectWidget {
|
||||||
/// Creates a widget that sizes its child to a fraction of the total available space.
|
/// Creates a widget that sizes its child to a fraction of the total available space.
|
||||||
@ -2269,7 +2278,7 @@ class ListBody extends MultiChildRenderObjectWidget {
|
|||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [Align], which sizes itself based on its child's size and positions
|
/// * [Align], which sizes itself based on its child's size and positions
|
||||||
/// the child according to a [Alignment] value.
|
/// the child according to an [Alignment] value.
|
||||||
/// * [CustomSingleChildLayout], which uses a delegate to control the layout of
|
/// * [CustomSingleChildLayout], which uses a delegate to control the layout of
|
||||||
/// a single child.
|
/// a single child.
|
||||||
/// * [CustomMultiChildLayout], which uses a delegate to position multiple
|
/// * [CustomMultiChildLayout], which uses a delegate to position multiple
|
||||||
@ -4023,7 +4032,7 @@ class RawImage extends LeafRenderObjectWidget {
|
|||||||
/// How to align the image within its bounds.
|
/// How to align the image within its bounds.
|
||||||
///
|
///
|
||||||
/// The alignment aligns the given position in the image to the given position
|
/// The alignment aligns the given position in the image to the given position
|
||||||
/// in the layout bounds. For example, a [Alignment] alignment of (-1.0,
|
/// in the layout bounds. For example, an [Alignment] alignment of (-1.0,
|
||||||
/// -1.0) aligns the image to the top-left corner of its layout bounds, while a
|
/// -1.0) aligns the image to the top-left corner of its layout bounds, while a
|
||||||
/// [Alignment] alignment of (1.0, 1.0) aligns the bottom right of the
|
/// [Alignment] alignment of (1.0, 1.0) aligns the bottom right of the
|
||||||
/// image with the bottom right corner of its layout bounds. Similarly, an
|
/// image with the bottom right corner of its layout bounds. Similarly, an
|
||||||
|
@ -106,6 +106,77 @@ void main() {
|
|||||||
expect(didReceiveTap, isTrue);
|
expect(didReceiveTap, isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('Transform AlignmentDirectional alignment', (WidgetTester tester) async {
|
||||||
|
bool didReceiveTap = false;
|
||||||
|
|
||||||
|
Widget buildFrame(TextDirection textDirection, AlignmentGeometry alignment) {
|
||||||
|
return new Directionality(
|
||||||
|
textDirection: textDirection,
|
||||||
|
child: new Stack(
|
||||||
|
children: <Widget>[
|
||||||
|
new Positioned(
|
||||||
|
top: 100.0,
|
||||||
|
left: 100.0,
|
||||||
|
child: new Container(
|
||||||
|
width: 100.0,
|
||||||
|
height: 100.0,
|
||||||
|
color: const Color(0xFF0000FF),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
new Positioned(
|
||||||
|
top: 100.0,
|
||||||
|
left: 100.0,
|
||||||
|
child: new Container(
|
||||||
|
width: 100.0,
|
||||||
|
height: 100.0,
|
||||||
|
child: new Transform(
|
||||||
|
transform: new Matrix4.diagonal3Values(0.5, 0.5, 1.0),
|
||||||
|
alignment: alignment,
|
||||||
|
child: new GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
didReceiveTap = true;
|
||||||
|
},
|
||||||
|
child: new Container(
|
||||||
|
color: const Color(0xFF00FFFF),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(TextDirection.ltr, AlignmentDirectional.centerEnd));
|
||||||
|
didReceiveTap = false;
|
||||||
|
await tester.tapAt(const Offset(110.0, 110.0));
|
||||||
|
expect(didReceiveTap, isFalse);
|
||||||
|
await tester.tapAt(const Offset(190.0, 150.0));
|
||||||
|
expect(didReceiveTap, isTrue);
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(TextDirection.rtl, AlignmentDirectional.centerStart));
|
||||||
|
didReceiveTap = false;
|
||||||
|
await tester.tapAt(const Offset(110.0, 110.0));
|
||||||
|
expect(didReceiveTap, isFalse);
|
||||||
|
await tester.tapAt(const Offset(190.0, 150.0));
|
||||||
|
expect(didReceiveTap, isTrue);
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(TextDirection.ltr, AlignmentDirectional.centerStart));
|
||||||
|
didReceiveTap = false;
|
||||||
|
await tester.tapAt(const Offset(190.0, 150.0));
|
||||||
|
expect(didReceiveTap, isFalse);
|
||||||
|
await tester.tapAt(const Offset(110.0, 150.0));
|
||||||
|
expect(didReceiveTap, isTrue);
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(TextDirection.rtl, AlignmentDirectional.centerEnd));
|
||||||
|
didReceiveTap = false;
|
||||||
|
await tester.tapAt(const Offset(190.0, 150.0));
|
||||||
|
expect(didReceiveTap, isFalse);
|
||||||
|
await tester.tapAt(const Offset(110.0, 150.0));
|
||||||
|
expect(didReceiveTap, isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('Transform offset + alignment', (WidgetTester tester) async {
|
testWidgets('Transform offset + alignment', (WidgetTester tester) async {
|
||||||
bool didReceiveTap = false;
|
bool didReceiveTap = false;
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user