Flutter GridView詳解

GridView常用構造

GridView

構造函數
GridView({Key key, Axis scrollDirection: Axis.vertical, bool reverse: false,
 ScrollController controller, bool primary, 
 ScrollPhysics physics, bool shrinkWrap: false,
  EdgeInsetsGeometry padding, 
 @required SliverGridDelegate gridDelegate, 
 bool addAutomaticKeepAlives: true,
  bool addRepaintBoundaries: true, 
 bool addSemanticIndexes: true,
  double cacheExtent, List<Widget> children: const [], 
  int semanticChildCount })
  
Creates a scrollable, 2D array of widgets with a custom SliverGridDelegate. [...]

GridView.count

構造函數
GridView.count({Key key, Axis scrollDirection: Axis.vertical, 
bool reverse: false, ScrollController controller, 
bool primary, ScrollPhysics physics, bool shrinkWrap: false, 
EdgeInsetsGeometry padding, @required int crossAxisCount,
 double mainAxisSpacing: 0.0, double crossAxisSpacing: 0.0, 
 double childAspectRatio: 1.0, bool addAutomaticKeepAlives: true,
  bool addRepaintBoundaries: true, 
  bool addSemanticIndexes: true,
   double cacheExtent, List<Widget> children: const [], 
   int semanticChildCount })
   
Creates a scrollable, 2D array of widgets with a fixed number of 
tiles in the cross axis. [...]
分析和使用
 Widget gridViewDefaultCount(List<BaseBean> list) {
    return GridView.count(
//      padding: EdgeInsets.all(5.0),
      //一行多少個
      crossAxisCount: 5,
      //滾動方向
      scrollDirection: Axis.vertical,
      // 左右間隔
      crossAxisSpacing: 10.0,
      // 上下間隔
      mainAxisSpacing: 10.0,
      //寬高比
      childAspectRatio: 2 / 5,

      children: initListWidget(list),
    );
  }

List<Widget> initListWidget(List<BaseBean> list) {
    List<Widget> lists = [];
    for (var item in list) {
      lists.add(new Container(
        height: 50.0,
        width: 50.0,
        color: Colors.yellow,
        child: new Center(
            child: new Text(
          item.age.toString(),
        )),
      ));
    }
    return lists;
  }

GridView.extent

構造函數
GridView.extent({Key key, Axis scrollDirection: Axis.vertical,
 bool reverse: false, ScrollController controller,
  bool primary, ScrollPhysics physics, 
  bool shrinkWrap: false, EdgeInsetsGeometry padding,
   @required double maxCrossAxisExtent,
    double mainAxisSpacing: 0.0, double crossAxisSpacing: 0.0,
     double childAspectRatio: 1.0, 
     bool addAutomaticKeepAlives: true,
      bool addRepaintBoundaries: true, 
      bool addSemanticIndexes: true,
       List<Widget> children: const [], 
       int semanticChildCount })
       
Creates a scrollable, 2D array of widgets with tiles that 
each have a maximum cross-axis extent. [...]
分析和使用
 ///GridView.extent 允許您指定項的最大像素寬度
  Widget gridViewDefaultExtent(List<BaseBean> list) {
    return GridView.extent(
      ///設置item的最大像素寬度  比如 130
      maxCrossAxisExtent: 130.0,

      ///其他屬性和count一樣
      children: initListWidget(list),
    );
  }

GridView.builder

構造函數
GridView.builder({Key key, Axis scrollDirection: Axis.vertical,
 bool reverse: false, ScrollController controller, 
 bool primary, ScrollPhysics physics,
  bool shrinkWrap: false, EdgeInsetsGeometry padding, 
  @required SliverGridDelegate gridDelegate, 
  @required IndexedWidgetBuilder itemBuilder,
   int itemCount, bool addAutomaticKeepAlives: true,
    bool addRepaintBoundaries: true, 
    bool addSemanticIndexes: true, 
    double cacheExtent, int semanticChildCount })
    
Creates a scrollable, 2D array of widgets that are created on demand. [...]
分析和使用
 ///GridView.builder  可以定義gridDelegate的模式
  Widget gridViewDefaultBuilder(List<BaseBean> list) {
    return GridView.builder(
        gridDelegate: MyGridViewDefaultCustom(
          crossAxisCount: 2,
          mainAxisSpacing: 10.0,
          crossAxisSpacing: 10.0,
          childAspectRatio: 1.0,
        ),
        itemBuilder: (context, i) => new Container(
              child: new Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  new Text(
                    "${list[i].name}",
                    style: new TextStyle(fontSize: 18.0, color: Colors.red),
                  ),
                  new Text(
                    "${list[i].age}",
                    style: new TextStyle(fontSize: 18.0, color: Colors.green),
                  ),
                  new Text(
                    "${list[i].content}",
                    style: new TextStyle(fontSize: 18.0, color: Colors.blue),
                  ),
                ],
              ),
            ));
  }
///自定義SliverGridDelegate
class MyGridViewDefaultCustom extends SliverGridDelegate {
  ///橫軸上的子節點數。  一行多少個child
  final int crossAxisCount;

  ///沿主軸的每個子節點之間的邏輯像素數。 默認垂直方向的子child間距  這裏的是主軸方向 當你改變 scrollDirection: Axis.vertical,就是改變了主軸發方向
  final double mainAxisSpacing;

  ///沿橫軸的每個子節點之間的邏輯像素數。默認水平方向的子child間距
  final double crossAxisSpacing;

  ///每個孩子的橫軸與主軸範圍的比率。 child的寬高比  常用來處理child的適配
  final double childAspectRatio;

  bool _debugAssertIsValid() {
    assert(mainAxisSpacing >= 0.0);
    assert(crossAxisSpacing >= 0.0);
    assert(childAspectRatio > 0.0);
    return true;
  }

  const MyGridViewDefaultCustom({
    @required this.crossAxisCount,
    this.mainAxisSpacing = 0.0,
    this.crossAxisSpacing = 0.0,
    this.childAspectRatio = 1.0,
  })  : assert(crossAxisCount != null && crossAxisCount > 0),
        assert(mainAxisSpacing != null && mainAxisSpacing >= 0),
        assert(crossAxisSpacing != null && crossAxisSpacing >= 0),
        assert(childAspectRatio != null && childAspectRatio > 0);

  ///  返回值有關網格中圖塊大小和位置的信息。這裏就是處理怎麼擺放 我們可以自己定義
  ///   SliverGridLayout是抽象類  SliverGridRegularTileLayout繼承於SliverGridLayout是抽象類
  @override
  SliverGridLayout getLayout(SliverConstraints constraints) {
    // TODO: implement getLayout
    assert(_debugAssertIsValid());

    ///對參數的修飾 自定義
    final double usableCrossAxisExtent =
        constraints.crossAxisExtent - crossAxisSpacing * (crossAxisCount - 1);
    final double childCrossAxisExtent = usableCrossAxisExtent / crossAxisCount;
    final double childMainAxisExtent = childCrossAxisExtent / childAspectRatio;
    return MySliverGridLayout(
      crossAxisCount: crossAxisCount,
      mainAxisStride: childMainAxisExtent + mainAxisSpacing,
      crossAxisStride: childCrossAxisExtent + crossAxisSpacing,
      childMainAxisExtent: childMainAxisExtent,
      childCrossAxisExtent: childCrossAxisExtent,
      reverseCrossAxis: axisDirectionIsReversed(constraints.crossAxisDirection),
    );
  }

  /// 和ListView的 shouldRebuild 作用一樣   之前的實例和新進來的實例是相同的就返回true
  @override
  bool shouldRelayout(SliverGridDelegate oldDelegate) {
    // TODO: implement shouldRelayout
    return true;
  }
}

GridView.custom

構造函數
GridView.custom({Key key, Axis scrollDirection: Axis.vertical,
 bool reverse: false, ScrollController controller, 
 bool primary, ScrollPhysics physics, 
 bool shrinkWrap: false, 
 EdgeInsetsGeometry padding,
  @required SliverGridDelegate gridDelegate,
  @required SliverChildDelegate childrenDelegate, 
  double cacheExtent,
   int semanticChildCount })
   
Creates a scrollable, 2D array of widgets with both a custom
 SliverGridDelegate and a custom SliverChildDelegate. [...]
分析和使用
 ///GridView.custom 就是自己定製規則
  /// 這裏說一下 GridView.count gridDelegate 其實就是內部實現 SliverGridDelegateWithFixedCrossAxisCount
  /// GridView.extent gridDelegate 其實就是內部實現 SliverGridDelegateWithMaxCrossAxisExtent
  Widget gridViewDefaultCustom(List<BaseBean> list) {
    return GridView.custom(
      gridDelegate: MyGridViewDefaultCustom(
        crossAxisCount: 2,
        mainAxisSpacing: 10.0,
        crossAxisSpacing: 10.0,
        childAspectRatio: 1.0,
      ),
      childrenDelegate: MyGridChildrenDelegate(
        (BuildContext context, int i) {
          return new Container(
              child: new Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              new Text(
                "${list[i].name}",
                style: new TextStyle(fontSize: 18.0, color: Colors.red),
              ),
              new Text(
                "${list[i].age}",
                style: new TextStyle(fontSize: 18.0, color: Colors.green),
              ),
              new Text(
                "${list[i].content}",
                style: new TextStyle(fontSize: 18.0, color: Colors.blue),
              ),
            ],
          ));
        },
        childCount: list.length,
      ),
    );
  }
/**
 * 繼承SliverChildBuilderDelegate  可以對列表的監聽
 */
class MyGridChildrenDelegate extends SliverChildBuilderDelegate {
  MyGridChildrenDelegate(
    Widget Function(BuildContext, int) builder, {
    int childCount,
    bool addAutomaticKeepAlive = true,
    bool addRepaintBoundaries = true,
  }) : super(builder,
            childCount: childCount,
            addAutomaticKeepAlives: addAutomaticKeepAlive,
            addRepaintBoundaries: addRepaintBoundaries);

  ///監聽 在可見的列表中 顯示的第一個位置和最後一個位置
  @override
  void didFinishLayout(int firstIndex, int lastIndex) {
    print('firstIndex: $firstIndex, lastIndex: $lastIndex');
  }

  ///可不重寫 重寫不能爲null  默認是true  添加進來的實例與之前的實例是否相同 相同返回true 反之false
  ///listView 暫時沒有看到應用場景 源碼中使用在 SliverFillViewport 中
  @override
  bool shouldRebuild(SliverChildBuilderDelegate oldDelegate) {
    // TODO: implement shouldRebuild
    print("oldDelegate$oldDelegate");
    return super.shouldRebuild(oldDelegate);
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章