parent
cd3715a854
commit
a30b109c9e
@ -32,7 +32,6 @@ export 'package:vector_math/vector_math_64.dart' show Matrix4;
|
||||
|
||||
export 'src/rendering/animated_size.dart';
|
||||
export 'src/rendering/binding.dart';
|
||||
export 'src/rendering/block.dart';
|
||||
export 'src/rendering/box.dart';
|
||||
export 'src/rendering/custom_layout.dart';
|
||||
export 'src/rendering/debug.dart';
|
||||
@ -42,6 +41,7 @@ export 'src/rendering/flex.dart';
|
||||
export 'src/rendering/flow.dart';
|
||||
export 'src/rendering/image.dart';
|
||||
export 'src/rendering/layer.dart';
|
||||
export 'src/rendering/list_body.dart';
|
||||
export 'src/rendering/node.dart';
|
||||
export 'src/rendering/object.dart';
|
||||
export 'src/rendering/paragraph.dart';
|
||||
|
@ -649,11 +649,15 @@ class _MergeableMaterialListBody extends ListBody {
|
||||
final List<MergeableMaterialItem> items;
|
||||
final List<BoxShadow> boxShadows;
|
||||
|
||||
AxisDirection _getDirection(BuildContext context) {
|
||||
return getAxisDirectionFromAxisReverseAndDirectionality(context, mainAxis, false);
|
||||
}
|
||||
|
||||
@override
|
||||
RenderListBody createRenderObject(BuildContext context) {
|
||||
return new _RenderMergeableMaterialListBody(
|
||||
mainAxis: mainAxis,
|
||||
boxShadows: boxShadows
|
||||
axisDirection: _getDirection(context),
|
||||
boxShadows: boxShadows,
|
||||
);
|
||||
}
|
||||
|
||||
@ -661,7 +665,7 @@ class _MergeableMaterialListBody extends ListBody {
|
||||
void updateRenderObject(BuildContext context, RenderListBody renderObject) {
|
||||
final _RenderMergeableMaterialListBody materialRenderListBody = renderObject;
|
||||
materialRenderListBody
|
||||
..mainAxis = mainAxis
|
||||
..axisDirection = _getDirection(context)
|
||||
..boxShadows = boxShadows;
|
||||
}
|
||||
}
|
||||
@ -669,9 +673,9 @@ class _MergeableMaterialListBody extends ListBody {
|
||||
class _RenderMergeableMaterialListBody extends RenderListBody {
|
||||
_RenderMergeableMaterialListBody({
|
||||
List<RenderBox> children,
|
||||
Axis mainAxis: Axis.vertical,
|
||||
AxisDirection axisDirection: AxisDirection.down,
|
||||
this.boxShadows
|
||||
}) : super(children: children, mainAxis: mainAxis);
|
||||
}) : super(children: children, axisDirection: axisDirection);
|
||||
|
||||
List<BoxShadow> boxShadows;
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:ui' show TextDirection;
|
||||
|
||||
export 'dart:ui' show
|
||||
BlendMode,
|
||||
BlurStyle,
|
||||
@ -157,3 +159,108 @@ enum VerticalDirection {
|
||||
/// The "start" is at the top, the "end" is at the bottom.
|
||||
down,
|
||||
}
|
||||
|
||||
/// A direction along either the horizontal or vertical [Axis].
|
||||
enum AxisDirection {
|
||||
/// Zero is at the bottom and positive values are above it: ⇈
|
||||
///
|
||||
/// Alphabetical content with a [GrowthDirection.forward] would have the A at
|
||||
/// the bottom and the Z at the top. This is an unusual configuration.
|
||||
up,
|
||||
|
||||
/// Zero is on the left and positive values are to the right of it: ⇉
|
||||
///
|
||||
/// Alphabetical content with a [GrowthDirection.forward] would have the A on
|
||||
/// the left and the Z on the right. This is the ordinary reading order for a
|
||||
/// horizontal set of tabs in an English application, for example.
|
||||
right,
|
||||
|
||||
/// Zero is at the top and positive values are below it: ⇊
|
||||
///
|
||||
/// Alphabetical content with a [GrowthDirection.forward] would have the A at
|
||||
/// the top and the Z at the bottom. This is the ordinary reading order for a
|
||||
/// vertical list.
|
||||
down,
|
||||
|
||||
/// Zero is to the right and positive values are to the left of it: ⇇
|
||||
///
|
||||
/// Alphabetical content with a [GrowthDirection.forward] would have the A at
|
||||
/// the right and the Z at the left. This is the ordinary reading order for a
|
||||
/// horizontal set of tabs in a Hebrew application, for example.
|
||||
left,
|
||||
}
|
||||
|
||||
/// Returns the [Axis] that contains the given [AxisDirection].
|
||||
///
|
||||
/// Specifically, returns [Axis.vertical] for [AxisDirection.up] and
|
||||
/// [AxisDirection.down] and returns [Axis.horizontal] for [AxisDirection.left]
|
||||
/// and [AxisDirection.right].
|
||||
Axis axisDirectionToAxis(AxisDirection axisDirection) {
|
||||
assert(axisDirection != null);
|
||||
switch (axisDirection) {
|
||||
case AxisDirection.up:
|
||||
case AxisDirection.down:
|
||||
return Axis.vertical;
|
||||
case AxisDirection.left:
|
||||
case AxisDirection.right:
|
||||
return Axis.horizontal;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns the [AxisDirection] in which reading occurs in the given [TextDirection].
|
||||
///
|
||||
/// Specifically, returns [AxisDirection.left] for [TextDirection.rtl] and
|
||||
/// [AxisDirection.right] for [TextDirection.ltr].
|
||||
AxisDirection textDirectionToAxisDirection(TextDirection textDirection) {
|
||||
assert(textDirection != null);
|
||||
switch (textDirection) {
|
||||
case TextDirection.rtl:
|
||||
return AxisDirection.left;
|
||||
case TextDirection.ltr:
|
||||
return AxisDirection.right;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns the opposite of the given [AxisDirection].
|
||||
///
|
||||
/// Specifically, returns [AxisDirection.up] for [AxisDirection.down] (and
|
||||
/// vice versa), as well as [AxisDirection.left] for [AxisDirection.right] (and
|
||||
/// vice versa).
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [flipAxis], which does the same thing for [Axis] values.
|
||||
AxisDirection flipAxisDirection(AxisDirection axisDirection) {
|
||||
assert(axisDirection != null);
|
||||
switch (axisDirection) {
|
||||
case AxisDirection.up:
|
||||
return AxisDirection.down;
|
||||
case AxisDirection.right:
|
||||
return AxisDirection.left;
|
||||
case AxisDirection.down:
|
||||
return AxisDirection.up;
|
||||
case AxisDirection.left:
|
||||
return AxisDirection.right;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns whether travelling along the given axis direction visits coordinates
|
||||
/// along that axis in numerically decreasing order.
|
||||
///
|
||||
/// Specifically, returns true for [AxisDirection.up] and [AxisDirection.left]
|
||||
/// and false for [AxisDirection.down] for [AxisDirection.right].
|
||||
bool axisDirectionIsReversed(AxisDirection axisDirection) {
|
||||
assert(axisDirection != null);
|
||||
switch (axisDirection) {
|
||||
case AxisDirection.up:
|
||||
case AxisDirection.left:
|
||||
return true;
|
||||
case AxisDirection.down:
|
||||
case AxisDirection.right:
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -31,8 +31,9 @@ class RenderListBody extends RenderBox
|
||||
/// By default, children are arranged along the vertical axis.
|
||||
RenderListBody({
|
||||
List<RenderBox> children,
|
||||
Axis mainAxis: Axis.vertical,
|
||||
}) : _mainAxis = mainAxis {
|
||||
AxisDirection axisDirection: AxisDirection.down,
|
||||
}) : assert(axisDirection != null),
|
||||
_axisDirection = axisDirection {
|
||||
addAll(children);
|
||||
}
|
||||
|
||||
@ -42,41 +43,17 @@ class RenderListBody extends RenderBox
|
||||
child.parentData = new ListBodyParentData();
|
||||
}
|
||||
|
||||
/// The direction to use as the main axis.
|
||||
Axis get mainAxis => _mainAxis;
|
||||
Axis _mainAxis;
|
||||
set mainAxis(Axis value) {
|
||||
if (_mainAxis != value) {
|
||||
_mainAxis = value;
|
||||
markNeedsLayout();
|
||||
}
|
||||
AxisDirection get axisDirection => _axisDirection;
|
||||
AxisDirection _axisDirection;
|
||||
set axisDirection(AxisDirection value) {
|
||||
assert(value != null);
|
||||
if (_axisDirection == value)
|
||||
return;
|
||||
_axisDirection = value;
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
BoxConstraints _getInnerConstraints(BoxConstraints constraints) {
|
||||
assert(_mainAxis != null);
|
||||
switch (_mainAxis) {
|
||||
case Axis.horizontal:
|
||||
return new BoxConstraints.tightFor(height: constraints.maxHeight);
|
||||
case Axis.vertical:
|
||||
return new BoxConstraints.tightFor(width: constraints.maxWidth);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
double get _mainAxisExtent {
|
||||
final RenderBox child = lastChild;
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
final BoxParentData parentData = child.parentData;
|
||||
assert(mainAxis != null);
|
||||
switch (mainAxis) {
|
||||
case Axis.horizontal:
|
||||
return parentData.offset.dx + child.size.width;
|
||||
case Axis.vertical:
|
||||
return parentData.offset.dy + child.size.height;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Axis get mainAxis => axisDirectionToAxis(axisDirection);
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
@ -124,41 +101,81 @@ class RenderListBody extends RenderBox
|
||||
'This is relatively expensive, however.' // (that's why we don't do it automatically)
|
||||
);
|
||||
}());
|
||||
final BoxConstraints innerConstraints = _getInnerConstraints(constraints);
|
||||
double position = 0.0;
|
||||
double mainAxisExtent = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
while (child != null) {
|
||||
child.layout(innerConstraints, parentUsesSize: true);
|
||||
final ListBodyParentData childParentData = child.parentData;
|
||||
switch (mainAxis) {
|
||||
case Axis.horizontal:
|
||||
childParentData.offset = new Offset(position, 0.0);
|
||||
position += child.size.width;
|
||||
break;
|
||||
case Axis.vertical:
|
||||
childParentData.offset = new Offset(0.0, position);
|
||||
position += child.size.height;
|
||||
break;
|
||||
switch (axisDirection) {
|
||||
case AxisDirection.right:
|
||||
final BoxConstraints innerConstraints = new BoxConstraints.tightFor(height: constraints.maxHeight);
|
||||
while (child != null) {
|
||||
child.layout(innerConstraints, parentUsesSize: true);
|
||||
final ListBodyParentData childParentData = child.parentData;
|
||||
childParentData.offset = new Offset(mainAxisExtent, 0.0);
|
||||
mainAxisExtent += child.size.width;
|
||||
assert(child.parentData == childParentData);
|
||||
child = childParentData.nextSibling;
|
||||
}
|
||||
assert(child.parentData == childParentData);
|
||||
child = childParentData.nextSibling;
|
||||
size = constraints.constrain(new Size(mainAxisExtent, constraints.maxHeight));
|
||||
break;
|
||||
case AxisDirection.left:
|
||||
final BoxConstraints innerConstraints = new BoxConstraints.tightFor(height: constraints.maxHeight);
|
||||
while (child != null) {
|
||||
child.layout(innerConstraints, parentUsesSize: true);
|
||||
final ListBodyParentData childParentData = child.parentData;
|
||||
mainAxisExtent += child.size.width;
|
||||
assert(child.parentData == childParentData);
|
||||
child = childParentData.nextSibling;
|
||||
}
|
||||
double position = 0.0;
|
||||
child = firstChild;
|
||||
while (child != null) {
|
||||
final ListBodyParentData childParentData = child.parentData;
|
||||
position += child.size.width;
|
||||
childParentData.offset = new Offset(mainAxisExtent - position, 0.0);
|
||||
assert(child.parentData == childParentData);
|
||||
child = childParentData.nextSibling;
|
||||
}
|
||||
size = constraints.constrain(new Size(mainAxisExtent, constraints.maxHeight));
|
||||
break;
|
||||
case AxisDirection.down:
|
||||
final BoxConstraints innerConstraints = new BoxConstraints.tightFor(width: constraints.maxWidth);
|
||||
while (child != null) {
|
||||
child.layout(innerConstraints, parentUsesSize: true);
|
||||
final ListBodyParentData childParentData = child.parentData;
|
||||
childParentData.offset = new Offset(0.0, mainAxisExtent);
|
||||
mainAxisExtent += child.size.height;
|
||||
assert(child.parentData == childParentData);
|
||||
child = childParentData.nextSibling;
|
||||
}
|
||||
size = constraints.constrain(new Size(constraints.maxWidth, mainAxisExtent));
|
||||
break;
|
||||
case AxisDirection.up:
|
||||
final BoxConstraints innerConstraints = new BoxConstraints.tightFor(width: constraints.maxWidth);
|
||||
while (child != null) {
|
||||
child.layout(innerConstraints, parentUsesSize: true);
|
||||
final ListBodyParentData childParentData = child.parentData;
|
||||
mainAxisExtent += child.size.height;
|
||||
assert(child.parentData == childParentData);
|
||||
child = childParentData.nextSibling;
|
||||
}
|
||||
double position = 0.0;
|
||||
child = firstChild;
|
||||
while (child != null) {
|
||||
final ListBodyParentData childParentData = child.parentData;
|
||||
position += child.size.height;
|
||||
childParentData.offset = new Offset(0.0, mainAxisExtent - position);
|
||||
assert(child.parentData == childParentData);
|
||||
child = childParentData.nextSibling;
|
||||
}
|
||||
size = constraints.constrain(new Size(constraints.maxWidth, mainAxisExtent));
|
||||
break;
|
||||
}
|
||||
switch (mainAxis) {
|
||||
case Axis.horizontal:
|
||||
size = constraints.constrain(new Size(_mainAxisExtent, constraints.maxHeight));
|
||||
break;
|
||||
case Axis.vertical:
|
||||
size = constraints.constrain(new Size(constraints.maxWidth, _mainAxisExtent));
|
||||
break;
|
||||
}
|
||||
|
||||
assert(size.isFinite);
|
||||
}
|
||||
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder description) {
|
||||
super.debugFillProperties(description);
|
||||
description.add(new EnumProperty<Axis>('mainAxis', mainAxis));
|
||||
description.add(new EnumProperty<AxisDirection>('axisDirection', axisDirection));
|
||||
}
|
||||
|
||||
double _getIntrinsicCrossAxis(_ChildSizingFunction childSize) {
|
@ -41,111 +41,6 @@ enum GrowthDirection {
|
||||
reverse,
|
||||
}
|
||||
|
||||
/// A direction along either the horizontal or vertical [Axis].
|
||||
enum AxisDirection {
|
||||
/// Zero is at the bottom and positive values are above it: ⇈
|
||||
///
|
||||
/// Alphabetical content with a [GrowthDirection.forward] would have the A at
|
||||
/// the bottom and the Z at the top. This is an unusual configuration.
|
||||
up,
|
||||
|
||||
/// Zero is on the left and positive values are to the right of it: ⇉
|
||||
///
|
||||
/// Alphabetical content with a [GrowthDirection.forward] would have the A on
|
||||
/// the left and the Z on the right. This is the ordinary reading order for a
|
||||
/// horizontal set of tabs in an English application, for example.
|
||||
right,
|
||||
|
||||
/// Zero is at the top and positive values are below it: ⇊
|
||||
///
|
||||
/// Alphabetical content with a [GrowthDirection.forward] would have the A at
|
||||
/// the top and the Z at the bottom. This is the ordinary reading order for a
|
||||
/// vertical list.
|
||||
down,
|
||||
|
||||
/// Zero is to the right and positive values are to the left of it: ⇇
|
||||
///
|
||||
/// Alphabetical content with a [GrowthDirection.forward] would have the A at
|
||||
/// the right and the Z at the left. This is the ordinary reading order for a
|
||||
/// horizontal set of tabs in a Hebrew application, for example.
|
||||
left,
|
||||
}
|
||||
|
||||
/// Returns the [Axis] that contains the given [AxisDirection].
|
||||
///
|
||||
/// Specifically, returns [Axis.vertical] for [AxisDirection.up] and
|
||||
/// [AxisDirection.down] and returns [Axis.horizontal] for [AxisDirection.left]
|
||||
/// and [AxisDirection.right].
|
||||
Axis axisDirectionToAxis(AxisDirection axisDirection) {
|
||||
assert(axisDirection != null);
|
||||
switch (axisDirection) {
|
||||
case AxisDirection.up:
|
||||
case AxisDirection.down:
|
||||
return Axis.vertical;
|
||||
case AxisDirection.left:
|
||||
case AxisDirection.right:
|
||||
return Axis.horizontal;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns the [AxisDirection] in which reading occurs in the given [TextDirection].
|
||||
///
|
||||
/// Specifically, returns [AxisDirection.left] for [TextDirection.rtl] and
|
||||
/// [AxisDirection.right] for [TextDirection.ltr].
|
||||
AxisDirection textDirectionToAxisDirection(TextDirection textDirection) {
|
||||
assert(textDirection != null);
|
||||
switch (textDirection) {
|
||||
case TextDirection.rtl:
|
||||
return AxisDirection.left;
|
||||
case TextDirection.ltr:
|
||||
return AxisDirection.right;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns the opposite of the given [AxisDirection].
|
||||
///
|
||||
/// Specifically, returns [AxisDirection.up] for [AxisDirection.down] (and
|
||||
/// vice versa), as well as [AxisDirection.left] for [AxisDirection.right] (and
|
||||
/// vice versa).
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [flipAxis], which does the same thing for [Axis] values.
|
||||
AxisDirection flipAxisDirection(AxisDirection axisDirection) {
|
||||
assert(axisDirection != null);
|
||||
switch (axisDirection) {
|
||||
case AxisDirection.up:
|
||||
return AxisDirection.down;
|
||||
case AxisDirection.right:
|
||||
return AxisDirection.left;
|
||||
case AxisDirection.down:
|
||||
return AxisDirection.up;
|
||||
case AxisDirection.left:
|
||||
return AxisDirection.right;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns whether travelling along the given axis direction visits coordinates
|
||||
/// along that axis in numerically decreasing order.
|
||||
///
|
||||
/// Specifically, returns true for [AxisDirection.up] and [AxisDirection.left]
|
||||
/// and false for [AxisDirection.down] for [AxisDirection.right].
|
||||
bool axisDirectionIsReversed(AxisDirection axisDirection) {
|
||||
assert(axisDirection != null);
|
||||
switch (axisDirection) {
|
||||
case AxisDirection.up:
|
||||
case AxisDirection.left:
|
||||
return true;
|
||||
case AxisDirection.down:
|
||||
case AxisDirection.right:
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Flips the [AxisDirection] if the [GrowthDirection] is [GrowthDirection.reverse].
|
||||
///
|
||||
/// Specifically, returns `axisDirection` if `growthDirection` is
|
||||
|
@ -2116,6 +2116,42 @@ class SliverPadding extends SingleChildRenderObjectWidget {
|
||||
|
||||
// LAYOUT NODES
|
||||
|
||||
/// Returns the [AxisDirection] in the given [Axis] in the current
|
||||
/// [Directionality] (or the reverse if `reverse` is true).
|
||||
///
|
||||
/// If `axis` is [Axis.vertical], this function returns [AxisDirection.down]
|
||||
/// unless `reverse` is true, in which case this function returns
|
||||
/// [AxisDirection.up].
|
||||
///
|
||||
/// If `axis` is [Axis.horizontal], this function checks the current
|
||||
/// [Directionality]. If the current [Directionality] is right-to-left, then
|
||||
/// this function returns [AxisDirection.left] (unless `reverse` is true, in
|
||||
/// which case it returns [AxisDirection.right]). Similarly, if the current
|
||||
/// [Directionality] is left-to-right, then this function returns
|
||||
/// [AxisDirection.right] (unless `reverse` is true, in which case it returns
|
||||
/// [AxisDirection.left]).
|
||||
///
|
||||
/// This function is used by a number of scrolling widgets (e.g., [ListView],
|
||||
/// [GridView], [PageView], and [SingleChildScrollView]) as well as [ListBody]
|
||||
/// to translate their [Axis] and `reverse` properties into a concrete
|
||||
/// [AxisDirection].
|
||||
AxisDirection getAxisDirectionFromAxisReverseAndDirectionality(
|
||||
BuildContext context,
|
||||
Axis axis,
|
||||
bool reverse,
|
||||
) {
|
||||
switch (axis) {
|
||||
case Axis.horizontal:
|
||||
assert(debugCheckHasDirectionality(context));
|
||||
final TextDirection textDirection = Directionality.of(context);
|
||||
final AxisDirection axisDirection = textDirectionToAxisDirection(textDirection);
|
||||
return reverse ? flipAxisDirection(axisDirection) : axisDirection;
|
||||
case Axis.vertical:
|
||||
return reverse ? AxisDirection.up : AxisDirection.down;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// A widget that arranges its children sequentially along a given axis, forcing
|
||||
/// them to the dimension of the parent in the other axis.
|
||||
///
|
||||
@ -2142,6 +2178,7 @@ class ListBody extends MultiChildRenderObjectWidget {
|
||||
ListBody({
|
||||
Key key,
|
||||
this.mainAxis: Axis.vertical,
|
||||
this.reverse: false,
|
||||
List<Widget> children: const <Widget>[],
|
||||
}) : assert(mainAxis != null),
|
||||
super(key: key, children: children);
|
||||
@ -2149,12 +2186,32 @@ class ListBody extends MultiChildRenderObjectWidget {
|
||||
/// The direction to use as the main axis.
|
||||
final Axis mainAxis;
|
||||
|
||||
/// Whether the list body positions children in the reading direction.
|
||||
///
|
||||
/// For example, if the reading direction is left-to-right and
|
||||
/// [mainAxis] is [Axis.horizontal], then the list body positions children
|
||||
/// from left to right when [reverse] is false and from right to left when
|
||||
/// [reverse] is true.
|
||||
///
|
||||
/// Similarly, if [mainAxis] is [Axis.vertical], then the list body positions
|
||||
/// from top to bottom when [reverse] is false and from bottom to top when
|
||||
/// [reverse] is true.
|
||||
///
|
||||
/// Defaults to false.
|
||||
final bool reverse;
|
||||
|
||||
AxisDirection _getDirection(BuildContext context) {
|
||||
return getAxisDirectionFromAxisReverseAndDirectionality(context, mainAxis, reverse);
|
||||
}
|
||||
|
||||
@override
|
||||
RenderListBody createRenderObject(BuildContext context) => new RenderListBody(mainAxis: mainAxis);
|
||||
RenderListBody createRenderObject(BuildContext context) {
|
||||
return new RenderListBody(axisDirection: _getDirection(context));
|
||||
}
|
||||
|
||||
@override
|
||||
void updateRenderObject(BuildContext context, RenderListBody renderObject) {
|
||||
renderObject.mainAxis = mainAxis;
|
||||
renderObject.axisDirection = _getDirection(context);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,6 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
import 'basic.dart';
|
||||
import 'debug.dart';
|
||||
import 'framework.dart';
|
||||
import 'primary_scroll_controller.dart';
|
||||
import 'scroll_controller.dart';
|
||||
@ -179,16 +178,7 @@ abstract class ScrollView extends StatelessWidget {
|
||||
/// [AxisDirection.right].
|
||||
@protected
|
||||
AxisDirection getDirection(BuildContext context) {
|
||||
switch (scrollDirection) {
|
||||
case Axis.horizontal:
|
||||
assert(debugCheckHasDirectionality(context));
|
||||
final TextDirection textDirection = Directionality.of(context);
|
||||
final AxisDirection axisDirection = textDirectionToAxisDirection(textDirection);
|
||||
return reverse ? flipAxisDirection(axisDirection) : axisDirection;
|
||||
case Axis.vertical:
|
||||
return reverse ? AxisDirection.up : AxisDirection.down;
|
||||
}
|
||||
return null;
|
||||
return getAxisDirectionFromAxisReverseAndDirectionality(context, scrollDirection, reverse);
|
||||
}
|
||||
|
||||
/// Subclasses should override this method to build the slivers for the inside
|
||||
|
@ -8,7 +8,6 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
import 'basic.dart';
|
||||
import 'debug.dart';
|
||||
import 'framework.dart';
|
||||
import 'primary_scroll_controller.dart';
|
||||
import 'scroll_controller.dart';
|
||||
@ -70,7 +69,7 @@ class SingleChildScrollView extends StatelessWidget {
|
||||
/// left to right when [reverse] is false and from right to left when
|
||||
/// [reverse] is true.
|
||||
///
|
||||
/// Similarly, if [scrollDirection] is [Axis.vertical], then scroll view
|
||||
/// Similarly, if [scrollDirection] is [Axis.vertical], then the scroll view
|
||||
/// scrolls from top to bottom when [reverse] is false and from bottom to top
|
||||
/// when [reverse] is true.
|
||||
///
|
||||
@ -116,16 +115,7 @@ class SingleChildScrollView extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
AxisDirection _getDirection(BuildContext context) {
|
||||
switch (scrollDirection) {
|
||||
case Axis.horizontal:
|
||||
assert(debugCheckHasDirectionality(context));
|
||||
final TextDirection textDirection = Directionality.of(context);
|
||||
final AxisDirection axisDirection = textDirectionToAxisDirection(textDirection);
|
||||
return reverse ? flipAxisDirection(axisDirection) : axisDirection;
|
||||
case Axis.vertical:
|
||||
return reverse ? AxisDirection.up : AxisDirection.down;
|
||||
}
|
||||
return null;
|
||||
return getAxisDirectionFromAxisReverseAndDirectionality(context, scrollDirection, reverse);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -17,7 +17,7 @@ void main() {
|
||||
final RenderListBody testBlock = new RenderListBody(
|
||||
children: <RenderBox>[
|
||||
paragraph,
|
||||
]
|
||||
],
|
||||
);
|
||||
|
||||
final double textWidth = paragraph.getMaxIntrinsicWidth(double.INFINITY);
|
||||
@ -52,7 +52,7 @@ void main() {
|
||||
expect(testBlock.getMaxIntrinsicHeight(0.0), equals(manyLinesTextHeight));
|
||||
|
||||
// horizontal block (same expectations again)
|
||||
testBlock.mainAxis = Axis.horizontal;
|
||||
testBlock.axisDirection = AxisDirection.right;
|
||||
expect(testBlock.getMinIntrinsicWidth(double.INFINITY), equals(wrappedTextWidth));
|
||||
expect(testBlock.getMaxIntrinsicWidth(double.INFINITY), equals(textWidth));
|
||||
expect(testBlock.getMinIntrinsicHeight(double.INFINITY), equals(oneLineTextHeight));
|
||||
|
109
packages/flutter/test/widgets/list_body_test.dart
Normal file
109
packages/flutter/test/widgets/list_body_test.dart
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright 2015 The Chromium 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_test/flutter_test.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
final List<Widget> children = <Widget>[
|
||||
new Container(width: 200.0, height: 150.0),
|
||||
new Container(width: 200.0, height: 150.0),
|
||||
new Container(width: 200.0, height: 150.0),
|
||||
new Container(width: 200.0, height: 150.0),
|
||||
];
|
||||
|
||||
void expectRects(WidgetTester tester, List<Rect> expected) {
|
||||
final Finder finder = find.byType(Container);
|
||||
finder.precache();
|
||||
final List<Rect> actual = <Rect>[];
|
||||
for (int i = 0; i < expected.length; ++i) {
|
||||
final Finder current = finder.at(i);
|
||||
expect(current, findsOneWidget);
|
||||
actual.add(tester.getRect(finder.at(i)));
|
||||
}
|
||||
expect(() => finder.at(expected.length), throwsRangeError);
|
||||
expect(actual, equals(expected));
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
||||
testWidgets('ListBody down', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(new Flex(
|
||||
direction: Axis.vertical,
|
||||
children: <Widget>[ new ListBody(children: children) ],
|
||||
));
|
||||
|
||||
expectRects(
|
||||
tester,
|
||||
<Rect>[
|
||||
new Rect.fromLTWH(0.0, 0.0, 800.0, 150.0),
|
||||
new Rect.fromLTWH(0.0, 150.0, 800.0, 150.0),
|
||||
new Rect.fromLTWH(0.0, 300.0, 800.0, 150.0),
|
||||
new Rect.fromLTWH(0.0, 450.0, 800.0, 150.0),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('ListBody up', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(new Flex(
|
||||
direction: Axis.vertical,
|
||||
children: <Widget>[ new ListBody(reverse: true, children: children) ],
|
||||
));
|
||||
|
||||
expectRects(
|
||||
tester,
|
||||
<Rect>[
|
||||
new Rect.fromLTWH(0.0, 450.0, 800.0, 150.0),
|
||||
new Rect.fromLTWH(0.0, 300.0, 800.0, 150.0),
|
||||
new Rect.fromLTWH(0.0, 150.0, 800.0, 150.0),
|
||||
new Rect.fromLTWH(0.0, 0.0, 800.0, 150.0),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('ListBody right', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(new Flex(
|
||||
textDirection: TextDirection.ltr,
|
||||
direction: Axis.horizontal,
|
||||
children: <Widget>[
|
||||
new Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: new ListBody(mainAxis: Axis.horizontal, children: children),
|
||||
),
|
||||
],
|
||||
));
|
||||
|
||||
expectRects(
|
||||
tester,
|
||||
<Rect>[
|
||||
new Rect.fromLTWH(0.0, 0.0, 200.0, 600.0),
|
||||
new Rect.fromLTWH(200.0, 0.0, 200.0, 600.0),
|
||||
new Rect.fromLTWH(400.0, 0.0, 200.0, 600.0),
|
||||
new Rect.fromLTWH(600.0, 0.0, 200.0, 600.0),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('ListBody left', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(new Flex(
|
||||
textDirection: TextDirection.ltr,
|
||||
direction: Axis.horizontal,
|
||||
children: <Widget>[
|
||||
new Directionality(
|
||||
textDirection: TextDirection.rtl,
|
||||
child: new ListBody(mainAxis: Axis.horizontal, children: children),
|
||||
),
|
||||
],
|
||||
));
|
||||
|
||||
expectRects(
|
||||
tester,
|
||||
<Rect>[
|
||||
new Rect.fromLTWH(600.0, 0.0, 200.0, 600.0),
|
||||
new Rect.fromLTWH(400.0, 0.0, 200.0, 600.0),
|
||||
new Rect.fromLTWH(200.0, 0.0, 200.0, 600.0),
|
||||
new Rect.fromLTWH(0.0, 0.0, 200.0, 600.0),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
@ -285,6 +285,10 @@ abstract class Finder {
|
||||
/// matched by this finder.
|
||||
Finder get last => new _LastFinder(this);
|
||||
|
||||
/// Returns a variant of this finder that only matches the element at the
|
||||
/// given index matched by this finder.
|
||||
Finder at(int index) => new _IndexFinder(this, index);
|
||||
|
||||
/// Returns a variant of this finder that only matches elements reachable by
|
||||
/// a hit test.
|
||||
///
|
||||
@ -335,6 +339,22 @@ class _LastFinder extends Finder {
|
||||
}
|
||||
}
|
||||
|
||||
class _IndexFinder extends Finder {
|
||||
_IndexFinder(this.parent, this.index);
|
||||
|
||||
final Finder parent;
|
||||
|
||||
final int index;
|
||||
|
||||
@override
|
||||
String get description => '${parent.description} (ignoring all but index $index)';
|
||||
|
||||
@override
|
||||
Iterable<Element> apply(Iterable<Element> candidates) sync* {
|
||||
yield parent.apply(candidates).elementAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
class _HitTestableFinder extends Finder {
|
||||
_HitTestableFinder(this.parent, this.alignment);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user