mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Previously we had totally wrong behavior. Now we have more correct behavior and testing. Fixes #1808
173 lines
4.6 KiB
Dart
173 lines
4.6 KiB
Dart
// 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 'dart:math' as math;
|
|
|
|
import 'box.dart';
|
|
import 'object.dart';
|
|
import 'viewport.dart';
|
|
|
|
/// Parent data for use with [RenderList].
|
|
class ListParentData extends ContainerBoxParentDataMixin<RenderBox> { }
|
|
|
|
class RenderList extends RenderVirtualViewport<ListParentData> {
|
|
RenderList({
|
|
List<RenderBox> children,
|
|
double itemExtent,
|
|
EdgeDims padding,
|
|
int virtualChildCount,
|
|
Offset paintOffset: Offset.zero,
|
|
Axis scrollDirection: Axis.vertical,
|
|
Painter overlayPainter,
|
|
LayoutCallback callback
|
|
}) : _itemExtent = itemExtent,
|
|
_padding = padding,
|
|
super(
|
|
virtualChildCount: virtualChildCount,
|
|
paintOffset: paintOffset,
|
|
scrollDirection: scrollDirection,
|
|
overlayPainter: overlayPainter,
|
|
callback: callback
|
|
) {
|
|
addAll(children);
|
|
}
|
|
|
|
double get itemExtent => _itemExtent;
|
|
double _itemExtent;
|
|
void set itemExtent (double newValue) {
|
|
assert(newValue != null);
|
|
if (_itemExtent == newValue)
|
|
return;
|
|
_itemExtent = newValue;
|
|
markNeedsLayout();
|
|
}
|
|
|
|
EdgeDims get padding => _padding;
|
|
EdgeDims _padding;
|
|
void set padding (EdgeDims newValue) {
|
|
if (_padding == newValue)
|
|
return;
|
|
_padding = newValue;
|
|
markNeedsLayout();
|
|
}
|
|
|
|
void setupParentData(RenderBox child) {
|
|
if (child.parentData is! ListParentData)
|
|
child.parentData = new ListParentData();
|
|
}
|
|
|
|
double get _scrollAxisPadding {
|
|
switch (scrollDirection) {
|
|
case Axis.vertical:
|
|
return padding.vertical;
|
|
case Axis.horizontal:
|
|
return padding.horizontal;
|
|
}
|
|
}
|
|
|
|
double get _preferredExtent {
|
|
if (itemExtent == null)
|
|
return double.INFINITY;
|
|
int count = virtualChildCount;
|
|
if (count == null)
|
|
return double.INFINITY;
|
|
double extent = itemExtent * count;
|
|
if (padding != null)
|
|
extent += _scrollAxisPadding;
|
|
return extent;
|
|
}
|
|
|
|
double _getIntrinsicWidth(BoxConstraints constraints) {
|
|
assert(constraints.debugAssertIsNormalized);
|
|
switch (scrollDirection) {
|
|
case Axis.vertical:
|
|
return constraints.constrainWidth(0.0);
|
|
case Axis.horizontal:
|
|
return constraints.constrainWidth(_preferredExtent);
|
|
}
|
|
}
|
|
|
|
double getMinIntrinsicWidth(BoxConstraints constraints) {
|
|
return _getIntrinsicWidth(constraints);
|
|
}
|
|
|
|
double getMaxIntrinsicWidth(BoxConstraints constraints) {
|
|
return _getIntrinsicWidth(constraints);
|
|
}
|
|
|
|
double _getIntrinsicHeight(BoxConstraints constraints) {
|
|
assert(constraints.debugAssertIsNormalized);
|
|
switch (scrollDirection) {
|
|
case Axis.vertical:
|
|
return constraints.constrainHeight(_preferredExtent);
|
|
case Axis.horizontal:
|
|
return constraints.constrainHeight(0.0);
|
|
}
|
|
}
|
|
|
|
double getMinIntrinsicHeight(BoxConstraints constraints) {
|
|
return _getIntrinsicHeight(constraints);
|
|
}
|
|
|
|
double getMaxIntrinsicHeight(BoxConstraints constraints) {
|
|
return _getIntrinsicHeight(constraints);
|
|
}
|
|
|
|
void performLayout() {
|
|
switch (scrollDirection) {
|
|
case Axis.vertical:
|
|
size = new Size(constraints.maxWidth,
|
|
constraints.constrainHeight(_preferredExtent));
|
|
break;
|
|
case Axis.horizontal:
|
|
size = new Size(constraints.constrainWidth(_preferredExtent),
|
|
constraints.maxHeight);
|
|
break;
|
|
}
|
|
|
|
if (callback != null)
|
|
invokeLayoutCallback(callback);
|
|
|
|
double itemWidth;
|
|
double itemHeight;
|
|
|
|
double x = 0.0;
|
|
double dx = 0.0;
|
|
|
|
double y = 0.0;
|
|
double dy = 0.0;
|
|
|
|
switch (scrollDirection) {
|
|
case Axis.vertical:
|
|
itemWidth = math.max(0.0, size.width - (padding == null ? 0.0 : padding.horizontal));
|
|
itemHeight = itemExtent ?? size.height;
|
|
x = padding != null ? padding.left : 0.0;
|
|
dy = itemHeight;
|
|
break;
|
|
case Axis.horizontal:
|
|
itemWidth = itemExtent ?? size.width;
|
|
itemHeight = math.max(0.0, size.height - (padding == null ? 0.0 : padding.vertical));
|
|
y = padding != null ? padding.top : 0.0;
|
|
dx = itemWidth;
|
|
break;
|
|
}
|
|
|
|
BoxConstraints innerConstraints =
|
|
new BoxConstraints.tightFor(width: itemWidth, height: itemHeight);
|
|
|
|
RenderBox child = firstChild;
|
|
while (child != null) {
|
|
child.layout(innerConstraints);
|
|
|
|
final ListParentData childParentData = child.parentData;
|
|
childParentData.offset = new Offset(x, y);
|
|
x += dx;
|
|
y += dy;
|
|
|
|
assert(child.parentData == childParentData);
|
|
child = childParentData.nextSibling;
|
|
}
|
|
}
|
|
}
|