[dynamic_layouts] Add a staggered grid layout example (#2559)

This commit is contained in:
Luis David López Magaña
2022-09-19 13:59:01 -05:00
committed by GitHub
parent 33554bab2f
commit a1b59e7df0
3 changed files with 130 additions and 1 deletions

View File

@ -4,6 +4,7 @@
import 'package:flutter/material.dart';
import 'staggered_layout_example.dart';
import 'wrap_layout_example.dart';
void main() {
@ -28,7 +29,6 @@ class MyApp extends StatelessWidget {
}
/// The home page
class MyHomePage extends StatelessWidget {
/// The home page constructor.
const MyHomePage({super.key});
@ -52,6 +52,16 @@ class MyHomePage extends StatelessWidget {
),
child: const Text('Wrap Demo'),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute<void>(
builder: (BuildContext context) => const StaggeredExample(),
),
),
child: const Text('Staggered Demo'),
),
],
),
),

View File

@ -0,0 +1,87 @@
// Copyright 2013 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:dynamic_layouts/dynamic_layouts.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const StaggeredExample());
}
/// A staggered layout example. Clicking the upper-right button will change
/// between a grid with a fixed cross axis count and one with a main axis
/// extent.
class StaggeredExample extends StatefulWidget {
/// Creates a [StaggeredExample].
const StaggeredExample({super.key});
@override
State<StaggeredExample> createState() => _StaggeredExampleState();
}
class _StaggeredExampleState extends State<StaggeredExample> {
final List<Widget> children = List<Widget>.generate(
50,
(int index) => _DynamicSizedTile(index: index),
);
bool fixedCrossAxisCount = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Staggered Layout Example'),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 50.0),
child: TextButton(
onPressed: () {
setState(() {
fixedCrossAxisCount = !fixedCrossAxisCount;
});
},
child: Text(
fixedCrossAxisCount ? 'FIXED' : 'MAX',
style: const TextStyle(color: Colors.white),
),
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
children.add(_DynamicSizedTile(index: children.length));
});
},
child: const Icon(Icons.plus_one),
),
body: fixedCrossAxisCount
? DynamicGridView.staggered(
crossAxisCount: 4,
children: <Widget>[...children],
)
: DynamicGridView.staggered(
maxCrossAxisExtent: 100,
children: <Widget>[...children],
),
);
}
}
class _DynamicSizedTile extends StatelessWidget {
const _DynamicSizedTile({required this.index});
final int index;
@override
Widget build(BuildContext context) {
return Container(
height: index % 3 * 50 + 20,
color: Colors.amber[(index % 8 + 1) * 100],
child: Text('Index $index'),
);
}
}

View File

@ -0,0 +1,32 @@
// Copyright 2013 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:example/staggered_layout_example.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('StaggeredExample lays out children correctly',
(WidgetTester tester) async {
tester.binding.window.physicalSizeTestValue = const Size(400, 200);
tester.binding.window.devicePixelRatioTestValue = 1.0;
await tester.pumpWidget(
const MaterialApp(
home: StaggeredExample(),
),
);
await tester.pumpAndSettle();
expect(find.text('Index 0'), findsOneWidget);
expect(tester.getTopLeft(find.text('Index 0')), const Offset(0.0, 56.0));
expect(find.text('Index 8'), findsOneWidget);
expect(tester.getTopLeft(find.text('Index 8')), const Offset(100.0, 146.0));
expect(find.text('Index 10'), findsOneWidget);
expect(
tester.getTopLeft(find.text('Index 10')),
const Offset(200.0, 196.0),
);
});
}