-
Notifications
You must be signed in to change notification settings - Fork 30.1k
Closed
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listf: scrollingViewports, list views, slivers, etc.Viewports, list views, slivers, etc.frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.waiting for PR to land (fixed)A fix is in flightA fix is in flight
Description
While writing tests for ensureVisible in 2D, found a bug in how the 2D viewport calculates the paint offset of the children when reversed.
Expected:
Actual:
import 'dart:math' as math;
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(const SimpleTest());
}
class SimpleTest extends StatelessWidget {
const SimpleTest({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SimpleTableView(
mainAxis: Axis.vertical,
primary: true,
verticalDetails: const ScrollableDetails.vertical(reverse: true),
horizontalDetails: const ScrollableDetails.horizontal(),
delegate: SimpleTableDelegate(builder: (context, vicinity) {
return Container(
decoration: BoxDecoration(
border: Border.all(),
color: vicinity.xIndex.isEven && vicinity.yIndex.isEven
? Colors.amber[100]
: (vicinity.xIndex.isOdd && vicinity.yIndex.isOdd
? Colors.blueAccent[100]
: null),
),
height: 200.0,
width: 200.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Checkbox(value: false, onChanged: (value) {}),
Text(vicinity.toString()),
],
),
);
}),
),
),
);
}
}
class SimpleTableDelegate extends TwoDimensionalChildBuilderDelegate {
SimpleTableDelegate({required super.builder});
}
class SimpleTableView extends TwoDimensionalScrollView {
const SimpleTableView({
super.key,
super.primary,
super.mainAxis = Axis.vertical,
super.verticalDetails = const ScrollableDetails.vertical(),
super.horizontalDetails = const ScrollableDetails.horizontal(),
required super.delegate,
super.cacheExtent,
super.diagonalDragBehavior = DiagonalDragBehavior.none,
super.dragStartBehavior = DragStartBehavior.start,
super.keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
super.clipBehavior = Clip.hardEdge,
});
@override
Widget buildViewport(BuildContext context, ViewportOffset verticalOffset,
ViewportOffset horizontalOffset) {
return SimpleTableViewport(
horizontalOffset: horizontalOffset,
horizontalAxisDirection: horizontalDetails.direction,
verticalOffset: verticalOffset,
verticalAxisDirection: verticalDetails.direction,
mainAxis: mainAxis,
delegate: delegate,
cacheExtent: cacheExtent,
clipBehavior: clipBehavior,
);
}
}
class SimpleTableViewport extends TwoDimensionalViewport {
const SimpleTableViewport({
super.key,
required super.verticalOffset,
required super.verticalAxisDirection,
required super.horizontalOffset,
required super.horizontalAxisDirection,
required super.delegate,
required super.mainAxis,
super.cacheExtent,
super.clipBehavior = Clip.hardEdge,
});
@override
SimpleTableDelegate get delegate => super.delegate as SimpleTableDelegate;
@override
RenderTwoDimensionalViewport createRenderObject(BuildContext context) {
return RenderSimpleTableViewport(
horizontalOffset: horizontalOffset,
horizontalAxisDirection: horizontalAxisDirection,
verticalOffset: verticalOffset,
verticalAxisDirection: verticalAxisDirection,
mainAxis: mainAxis,
delegate: delegate,
childManager: context as TwoDimensionalChildManager,
cacheExtent: cacheExtent,
clipBehavior: clipBehavior,
);
}
@override
void updateRenderObject(
BuildContext context, RenderSimpleTableViewport renderObject) {
renderObject
..horizontalOffset = horizontalOffset
..horizontalAxisDirection = horizontalAxisDirection
..verticalOffset = verticalOffset
..verticalAxisDirection = verticalAxisDirection
..mainAxis = mainAxis
..delegate = delegate
..cacheExtent = cacheExtent
..clipBehavior = clipBehavior;
}
}
class RenderSimpleTableViewport extends RenderTwoDimensionalViewport {
RenderSimpleTableViewport({
required super.horizontalOffset,
required super.horizontalAxisDirection,
required super.verticalOffset,
required super.verticalAxisDirection,
required super.delegate,
required super.mainAxis,
required super.childManager,
super.cacheExtent,
super.clipBehavior = Clip.hardEdge,
});
@override
void layoutChildSequence() {
// Every child is 200x200 square
final double horizontalPixels = horizontalOffset.pixels;
final double verticalPixels = verticalOffset.pixels;
final int leadingColumn = math.max((horizontalPixels / 200).floor(), 0);
final int trailingColumn = math.min(
((horizontalPixels + viewportDimension.width + cacheExtent) / 200).ceil(),
99,
);
final int leadingRow = math.max((verticalPixels / 200).floor(), 0);
final int trailingRow = math.min(
((verticalPixels + viewportDimension.height + cacheExtent) / 200).ceil(),
99,
);
double xLayoutOffset = (leadingColumn * 200) - horizontalOffset.pixels;
for (int column = leadingColumn; column <= trailingColumn; column++) {
double yLayoutOffset = (leadingRow * 200) - verticalOffset.pixels;
for (int row = leadingRow; row <= trailingRow; row++) {
final ChildVicinity vicinity = ChildVicinity(xIndex: column, yIndex: row);
final RenderBox child = buildOrObtainChildFor(vicinity)!;
child.layout(constraints, parentUsesSize: true);
parentDataOf(child).layoutOffset = Offset(xLayoutOffset, yLayoutOffset);
yLayoutOffset += 200;
}
xLayoutOffset += 200;
}
verticalOffset.applyContentDimensions(
0,
200 * 100 - viewportDimension.height,
);
horizontalOffset.applyContentDimensions(
0,
200 * 100 - viewportDimension.width,
);
}
}
I have a fix on the way...
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listf: scrollingViewports, list views, slivers, etc.Viewports, list views, slivers, etc.frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.waiting for PR to land (fixed)A fix is in flightA fix is in flight
Type
Projects
Status
Done

