mirror of
https://github.com/flutter/packages.git
synced 2025-07-02 08:34:31 +08:00
[dynamic_layouts] Add a staggered grid layout example (#2559)
This commit is contained in:

committed by
GitHub

parent
33554bab2f
commit
a1b59e7df0
@ -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'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -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'),
|
||||
);
|
||||
}
|
||||
}
|
@ -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),
|
||||
);
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user