flutter/examples/api/lib/widgets/interactive_viewer/interactive_viewer.builder.0.dart
Michael Goderbauer 5491c8c146
Auto-format Framework (#160545)
This auto-formats all *.dart files in the repository outside of the
`engine` subdirectory and enforces that these files stay formatted with
a presubmit check.

**Reviewers:** Please carefully review all the commits except for the
one titled "formatted". The "formatted" commit was auto-generated by
running `dev/tools/format.sh -a -f`. The other commits were hand-crafted
to prepare the repo for the formatting change. I recommend reviewing the
commits one-by-one via the "Commits" tab and avoiding Github's "Files
changed" tab as it will likely slow down your browser because of the
size of this PR.

---------

Co-authored-by: Kate Lovett <katelovett@google.com>
Co-authored-by: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com>
2024-12-19 20:06:21 +00:00

135 lines
4.1 KiB
Dart

// Copyright 2014 The Flutter 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/material.dart';
import 'package:vector_math/vector_math_64.dart' show Quad, Vector3;
/// Flutter code sample for [InteractiveViewer.builder].
void main() => runApp(const IVBuilderExampleApp());
class IVBuilderExampleApp extends StatelessWidget {
const IVBuilderExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('IV Builder Example')),
body: const _IVBuilderExample(),
),
);
}
}
class _IVBuilderExample extends StatefulWidget {
const _IVBuilderExample();
@override
State<_IVBuilderExample> createState() => _IVBuilderExampleState();
}
class _IVBuilderExampleState extends State<_IVBuilderExample> {
static const double _cellWidth = 160.0;
static const double _cellHeight = 80.0;
// Returns the axis aligned bounding box for the given Quad, which might not
// be axis aligned.
Rect axisAlignedBoundingBox(Quad quad) {
double xMin = quad.point0.x;
double xMax = quad.point0.x;
double yMin = quad.point0.y;
double yMax = quad.point0.y;
for (final Vector3 point in <Vector3>[quad.point1, quad.point2, quad.point3]) {
if (point.x < xMin) {
xMin = point.x;
} else if (point.x > xMax) {
xMax = point.x;
}
if (point.y < yMin) {
yMin = point.y;
} else if (point.y > yMax) {
yMax = point.y;
}
}
return Rect.fromLTRB(xMin, yMin, xMax, yMax);
}
@override
Widget build(BuildContext context) {
return Center(
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return InteractiveViewer.builder(
boundaryMargin: const EdgeInsets.all(double.infinity),
builder: (BuildContext context, Quad viewport) {
return _TableBuilder(
cellWidth: _cellWidth,
cellHeight: _cellHeight,
viewport: axisAlignedBoundingBox(viewport),
builder: (BuildContext context, int row, int column) {
return Container(
height: _cellHeight,
width: _cellWidth,
color: row % 2 + column % 2 == 1 ? Colors.white : Colors.grey.withOpacity(0.1),
child: Align(child: Text('$row x $column')),
);
},
);
},
);
},
),
);
}
}
typedef _CellBuilder = Widget Function(BuildContext context, int row, int column);
class _TableBuilder extends StatelessWidget {
const _TableBuilder({
required this.cellWidth,
required this.cellHeight,
required this.viewport,
required this.builder,
});
final double cellWidth;
final double cellHeight;
final Rect viewport;
final _CellBuilder builder;
@override
Widget build(BuildContext context) {
final int firstRow = (viewport.top / cellHeight).floor();
final int lastRow = (viewport.bottom / cellHeight).ceil();
final int firstCol = (viewport.left / cellWidth).floor();
final int lastCol = (viewport.right / cellWidth).ceil();
// This will create and render exactly (lastRow - firstRow) * (lastCol - firstCol) cells
return SizedBox(
// Stack needs constraints, even though we then Clip.none outside of them.
// InteractiveViewer.builder always sets constrained to false, giving infinite constraints to the child.
// See: https://api.flutter.dev/flutter/widgets/InteractiveViewer/constrained.html
width: 1,
height: 1,
child: Stack(
clipBehavior: Clip.none,
children: <Widget>[
for (int row = firstRow; row < lastRow; row++)
for (int col = firstCol; col < lastCol; col++)
Positioned(
left: col * cellWidth,
top: row * cellHeight,
child: builder(context, row, col),
),
],
),
);
}
}