在网格视图中颤动可扩展的瓷砖
Flutter expandable tiles inside grid view
我正在尝试在 flutter 上实现此功能,但老实说不知道该怎么做。几个星期以来我一直在努力弄明白,我尝试了 flutter_staggered_grid_view,这是最接近这个的,但这也没有帮助。有人知道如何实现这种效果吗?
您可以将 Wrap 小部件用作网格,并使用一些带有 AnimatedContainer 的自定义小部件来展开和缩回块。
//number of childs used in the example
static const itemCount = 8;
//list of each bloc expandable state, that is changed to trigger the animation of the AnimatedContainer
List<bool> expandableState = List.generate(itemCount, (index) => false);
Widget bloc (double width, int index) {
bool isExpanded = expandableState[index];
return GestureDetector(
onTap: () {
setState(() {
//changing the current expandableState
expandableState[index] = !isExpanded;
});
},
child: AnimatedContainer(
duration: Duration(milliseconds: 200),
margin: const EdgeInsets.all(20.0),
width: !isExpanded ? width * 0.4 : width * 0.8,
height: !isExpanded ? width * 0.4 : width * 0.8,
color: Colors.red,
),
);
}
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
return Scaffold(
body: Align(
child: SingleChildScrollView(
child: Wrap(
children: List.generate(itemCount, (index) {
return bloc(width, index);
}),
),
),
),
);
}
您可以使用 Wrap 小部件来实现结果。请看下面的代码。
import 'package:flutter/material.dart';
final Color darkBlue = const Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: const Text("Demo")),
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
final int _cells = 8;
final double _containerSizeSmall = 75;
final double _containerSizeLarge = 170;
final double _padding = 10;
int _clicked = 0;
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
return SingleChildScrollView(
child: Container(
height: size.height,
width: 240,
child: Wrap(
children: List.generate(
_cells,
(col) => Padding(
padding: EdgeInsets.all(_padding),
child: GestureDetector(
onTap: () {
setState(() {
_clicked != col + 1 ? _clicked = col + 1 : _clicked = 0;
});
},
child: Container(
height: _clicked == col + 1
? _containerSizeLarge
: _containerSizeSmall,
width: _clicked == col + 1
? _containerSizeLarge
: _containerSizeSmall,
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: const BorderRadius.all(
const Radius.circular(5),
),
),
child: Center(child: Text('${col + 1}')),
),
),
),
),
),
),
);
}
}
您可以列出应展开的项目并将它们相应地放置在网格视图中(例如使用 flutter_staggered_grid_view)。
我编辑了编写的示例 in the library docs 以实现以下结果:
基本上,
创建一个 StatefulWidget
并向其添加一个列表 (_expandedIndices
)。该列表的目的是跟踪展开的项目的索引。
在网格单元格上添加一个 GestureDetector
以检测列表中的点击和 add/remove 索引(如果索引不存在,则将其添加到列表中,否则删除它)。
Don't forget to put the code that updates the list inside a setState
.
- 在
staggeredTileBuilder
中配置 crossAxisCellCount
和 mainAxisCellCount
基于 index
中的项目是否应该展开。
class StaggeredGridViewWithExpandableCells extends StatefulWidget {
@override
_StaggeredGridViewWithExpandableCellsState createState() =>
_StaggeredGridViewWithExpandableCellsState();
}
class _StaggeredGridViewWithExpandableCellsState
extends State<StaggeredGridViewWithExpandableCells> {
final _expandedIndices = Set<int>();
@override
Widget build(BuildContext context) {
return StaggeredGridView.countBuilder(
crossAxisCount: 4,
itemCount: 16,
itemBuilder: (BuildContext context, int index) => GestureDetector(
onTap: () => setState(() => _expandedIndices.contains(index) ? _expandedIndices.remove(index) : _expandedIndices.add(index)),
child: new Container(
color: Colors.green,
child: new Center(
child: new CircleAvatar(
backgroundColor: Colors.white,
child: new Text('$index'),
),
)),
),
staggeredTileBuilder: (int index) =>
new StaggeredTile.count(_expandedIndices.contains(index) ? 4 : 2, 1),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
);
}
}
我正在尝试在 flutter 上实现此功能,但老实说不知道该怎么做。几个星期以来我一直在努力弄明白,我尝试了 flutter_staggered_grid_view,这是最接近这个的,但这也没有帮助。有人知道如何实现这种效果吗?
您可以将 Wrap 小部件用作网格,并使用一些带有 AnimatedContainer 的自定义小部件来展开和缩回块。
//number of childs used in the example
static const itemCount = 8;
//list of each bloc expandable state, that is changed to trigger the animation of the AnimatedContainer
List<bool> expandableState = List.generate(itemCount, (index) => false);
Widget bloc (double width, int index) {
bool isExpanded = expandableState[index];
return GestureDetector(
onTap: () {
setState(() {
//changing the current expandableState
expandableState[index] = !isExpanded;
});
},
child: AnimatedContainer(
duration: Duration(milliseconds: 200),
margin: const EdgeInsets.all(20.0),
width: !isExpanded ? width * 0.4 : width * 0.8,
height: !isExpanded ? width * 0.4 : width * 0.8,
color: Colors.red,
),
);
}
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
return Scaffold(
body: Align(
child: SingleChildScrollView(
child: Wrap(
children: List.generate(itemCount, (index) {
return bloc(width, index);
}),
),
),
),
);
}
您可以使用 Wrap 小部件来实现结果。请看下面的代码。
import 'package:flutter/material.dart';
final Color darkBlue = const Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: const Text("Demo")),
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
final int _cells = 8;
final double _containerSizeSmall = 75;
final double _containerSizeLarge = 170;
final double _padding = 10;
int _clicked = 0;
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
return SingleChildScrollView(
child: Container(
height: size.height,
width: 240,
child: Wrap(
children: List.generate(
_cells,
(col) => Padding(
padding: EdgeInsets.all(_padding),
child: GestureDetector(
onTap: () {
setState(() {
_clicked != col + 1 ? _clicked = col + 1 : _clicked = 0;
});
},
child: Container(
height: _clicked == col + 1
? _containerSizeLarge
: _containerSizeSmall,
width: _clicked == col + 1
? _containerSizeLarge
: _containerSizeSmall,
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: const BorderRadius.all(
const Radius.circular(5),
),
),
child: Center(child: Text('${col + 1}')),
),
),
),
),
),
),
);
}
}
您可以列出应展开的项目并将它们相应地放置在网格视图中(例如使用 flutter_staggered_grid_view)。
我编辑了编写的示例 in the library docs 以实现以下结果:
基本上,
创建一个
StatefulWidget
并向其添加一个列表 (_expandedIndices
)。该列表的目的是跟踪展开的项目的索引。在网格单元格上添加一个
GestureDetector
以检测列表中的点击和 add/remove 索引(如果索引不存在,则将其添加到列表中,否则删除它)。
Don't forget to put the code that updates the list inside a
setState
.
- 在
staggeredTileBuilder
中配置crossAxisCellCount
和mainAxisCellCount
基于index
中的项目是否应该展开。
class StaggeredGridViewWithExpandableCells extends StatefulWidget {
@override
_StaggeredGridViewWithExpandableCellsState createState() =>
_StaggeredGridViewWithExpandableCellsState();
}
class _StaggeredGridViewWithExpandableCellsState
extends State<StaggeredGridViewWithExpandableCells> {
final _expandedIndices = Set<int>();
@override
Widget build(BuildContext context) {
return StaggeredGridView.countBuilder(
crossAxisCount: 4,
itemCount: 16,
itemBuilder: (BuildContext context, int index) => GestureDetector(
onTap: () => setState(() => _expandedIndices.contains(index) ? _expandedIndices.remove(index) : _expandedIndices.add(index)),
child: new Container(
color: Colors.green,
child: new Center(
child: new CircleAvatar(
backgroundColor: Colors.white,
child: new Text('$index'),
),
)),
),
staggeredTileBuilder: (int index) =>
new StaggeredTile.count(_expandedIndices.contains(index) ? 4 : 2, 1),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
);
}
}