flutter入门之通过GridView和PageView实现展示item的功能
【原创不易,转载请注明出处:https://blog.csdn.net/email_jade/article/details/87915598】
今天给大家带来的是一个非常常见的布局,通过GridView和PageView实现类似于聊天表情emoji布局的功能,我们先来看一下效果吧:
看了标题大家应该清楚,组成该布局的主体元素是GridView和PageView。
我们来分解一下布局,布局见上下两部分,上面的图标和下面的页指示器,页指示器比较简单,一个居中的Row布局搞定,如下,其中_pageCount代表总页数:
///页标
Widget _buildCursor() {
List<Widget> list = List();
for (int i = 0; i < _pageCount; i++) {
list.add(_buildPoint(_currentPage == i));
}
return Container(
child: Row(
children: list,
mainAxisSize: MainAxisSize.min,
),
alignment: AlignmentDirectional.center,
);
}
///单个点
Widget _buildPoint(bool focus) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Container(
width: 10, height: 10, color: focus ? Colors.black : Colors.grey),
);
}
图标部分,单页可以看做是一个GridView,而多个GridView又组成了一个PageView,由于翻页的时候要联动下面的页指示器跟着改变,因此要使用到PageView的PageController动态改变页数,代码如下,要记得及时释放controller:
final List<Widget> children;
final int column; //列数
final int row; //行数
final double columnSpacing; //列间隔
final double rowSpacing; //行间隔
final double itemRatio; //每个item的宽高比,默认正方形
。。。。
///每页的个数
int _countPerPage;
///总页数
int _pageCount;
///当前页
int _currentPage;
///控制器
PageController _controller;
///计算总页数及单页的item数目
void _calculatePage() {
assert(widget.children != null);
_countPerPage = widget.row * widget.column;
_pageCount = (widget.children.length / _countPerPage).ceil();
}
///多个Item构建单页的GridView
Widget _buildGrid(List<Widget> list) {
return GridView.count(
crossAxisCount: widget.column,
children: list,
mainAxisSpacing: widget.rowSpacing,
crossAxisSpacing: widget.columnSpacing,
childAspectRatio: widget.itemRatio,
);
}
///构建多个GridView
List<Widget> _buildPages() {
List<Widget> list = List();
int index = 0;
int realIndex;
for (int i = 0; i < _pageCount; i++) {
realIndex = index + _countPerPage > widget.children.length
? widget.children.length
: index + _countPerPage;
List l = widget.children.sublist(index, realIndex);
index = realIndex;
list.add(_buildGrid(l));
}
return list;
}
///多个GridView构建PageView
Widget _buildPageView() {
return PageView(
controller: _controller,
children: _buildPages(),
onPageChanged: (page) {
setState(() {
_currentPage = page;
});
},
);
}
布局已经完成,比较简单。当然,其实有很多内容可以扩展,比如可以通过Container的BoxDecoration shape属性shape: BoxShape.circle改变页指示器为圆形,也可以通过修改item动态改变样式,比如说是图片和标题组成的Item,等等,都由实际情况来决定,只要大体结构不变,就可以使用此模块。
下面是使用部分,演示的时候用到了fluttertoast控件:
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
home: GridPage(children: _buildChildren(), column: 7, row: 4,),
);
}
///构建数据
List<Widget> _buildChildren(){
List<Widget> list = List();
for(int i=0; i<133; i++){
list.add(GestureDetector(child:Icon(Icons.android, color: Colors.green, size: 40.0,), onTap: (){
Fluttertoast.showToast(msg: "item $i on click");
},),);
}
return list;
}
}
完整代码见:
https://github.com/jadennn/flutter_grid_page
flutter很好,路还很长,让我们一起奋斗前行!
下一篇: Flutter环境的搭建