【发布时间】:2021-03-04 06:46:04
【问题描述】:
我正在尝试在颤振上实现此功能,但老实说不知道该怎么做。几周以来我一直在努力解决这个问题,我尝试了 flutter_staggered_grid_view,这是最接近这个的,但这也无济于事。有没有人知道如何实现这个效果?
【问题讨论】:
标签: flutter flutter-layout flutter-gridview
我正在尝试在颤振上实现此功能,但老实说不知道该怎么做。几周以来我一直在努力解决这个问题,我尝试了 flutter_staggered_grid_view,这是最接近这个的,但这也无济于事。有没有人知道如何实现这个效果?
【问题讨论】:
标签: flutter flutter-layout flutter-gridview
您可以将 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);
}),
),
),
),
);
}
【讨论】:
您可以有一个应该展开的项目列表,并相应地将它们布置在网格视图中(例如使用 flutter_staggered_grid_view)。
我编辑了写成in the library docs的例子,得到如下结果:
基本上,
创建一个StatefulWidget 并向其中添加一个列表 (_expandedIndices)。列表的目的是跟踪展开的项目的索引。
在网格单元格上添加GestureDetector 以检测点击并从列表中添加/删除索引(如果索引不存在,则将其添加到列表中,否则将其删除)。
不要忘记将更新列表的代码放在
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,
);
}
}
【讨论】:
您可以使用 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}')),
),
),
),
),
),
),
);
}
}
【讨论】: