欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

flutter入门之通过GridView和PageView实现展示item的功能

程序员文章站 2022-05-29 20:26:32
...

    【原创不易,转载请注明出处:https://blog.csdn.net/email_jade/article/details/87915598

    今天给大家带来的是一个非常常见的布局,通过GridViewPageView实现类似于聊天表情emoji布局的功能,我们先来看一下效果吧:

flutter入门之通过GridView和PageView实现展示item的功能

    看了标题大家应该清楚,组成该布局的主体元素是GridViewPageView

    我们来分解一下布局,布局见上下两部分,上面的图标和下面的页指示器,页指示器比较简单,一个居中的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很好,路还很长,让我们一起奋斗前行!