Flutter布局入門

Flutter布局入門

一、Widget簡介

描述

Fullter的核心思想是用widget 來構(gòu)建你的 UI 界面。 Widget 描述了在當(dāng)前的配置和狀態(tài)下視圖所應(yīng)該呈現(xiàn)的樣子。當(dāng) widget 的狀態(tài)改變時,它會重新構(gòu)建其描述(展示的 UI),框架則會對比前后變化的不同,以確定底層渲染樹從一個狀態(tài)轉(zhuǎn)換到下一個狀態(tài)所需的最小更改。

以上是Widget官方解釋,所以Widget和我們通常所說的View不一樣,widget不是一個控件,它是對控件的描述(我們在入門時并不需要太過糾結(jié)Widget是什么,只需知道它是構(gòu)建UI即可)。

下面我們官方demo,神圣的“Hello World”
import 'package:flutter/material.dart';

void main() {
  runApp(
    Center(
      child: Text(
        'Hello, world!',
        textDirection: TextDirection.ltr,
      ),
    ),
  );
}

這個demo官方文檔有相關(guān)解釋有興趣的可以查看,就不具體贅述了,具體的Center Text會在后面詳解。

1.2、Widget分類

Widget的種類有很多,官方做了如下分類

  • Accessibility
  • Animation and Motion 給你的應(yīng)用程序添加動畫。
  • Assets, Images, and Icons
  • Async Flutter應(yīng)用程序的異步Widget。
  • Basics 在構(gòu)建第一個Flutter應(yīng)用程序之前,需要知道的Basics Widget。
  • Cupertino (iOS-style widgets) iOS風(fēng)格的Widget。
  • Input 除了在Material Components和Cupertino中的輸入Widget外,還可以接受用戶輸入的Widget。
  • Interaction Models 響應(yīng)觸摸事件并將用戶路由到不同的視圖中。
  • Layout 用于布局的Widget。
  • Material Components Material Design風(fēng)格的Widget。
  • Painting and effects 不改變布局、大小、位置的情況下為子Widget應(yīng)用視覺效果。
  • Scrolling 滾動相關(guān)的Widget。
  • Styling 主題、填充相關(guān)Widget。
  • Text 顯示文本和文本樣式。

Widget詳解

Widget類

在Widget的構(gòu)造方法中有一個參數(shù)key

 /// Initializes [key] for subclasses.
  const Widget({ this.key });

這個key的作用是用來控制在widget樹中替換widget的時候使用的,key作為唯一標(biāo)識。

State

我們常用的Widget有兩種,StatelessWidget、StatefulWidget,在了解State之前,看下二者之間的區(qū)別,其實(shí)可以根據(jù)字面意思大致猜到

  • StatelessWidget:無中間狀態(tài)變化的 widget,需要更新展示內(nèi)容的話,就得通過重新 new。
  • StatefulWidget:具有可變狀態(tài)(State)的Widget,在狀態(tài)改變是調(diào)用State.setState()通知狀態(tài)改變,刷新狀態(tài)
State生命周期

State生命周期可以分為三個階段:

  1. 初始化:
  2. 狀態(tài)改變:
  3. 銷毀:


    state生命周期
完整的生命周期
  • initState:widget創(chuàng)建執(zhí)行的第一個方法,可以再里面初始化一些數(shù)據(jù),以及綁定控制器

  • didChangeDependencies :當(dāng)State對象的依賴發(fā)生變化時會被調(diào)用;例如:在之前build()中包含了一個InheritedWidget,然后在之后的build() 中InheritedWidget發(fā)生了變化,那么此時InheritedWidget的子widget的didChangeDependencies()回調(diào)都會被調(diào)用。InheritedWidget這個widget可以由父控件向子控件共享數(shù)據(jù)。

  • reassemble:此回調(diào)是專門為了開發(fā)調(diào)試而提供的,在熱重載(hot reload)時會被調(diào)用,此回調(diào)在Release模式下永遠(yuǎn)不會被調(diào)用。

  • didUpdateWidget:當(dāng)樹rebuid的時候會調(diào)用該方法。

  • deactivate:當(dāng)State對象從樹中被移除時,會調(diào)用此回調(diào)。

  • dispose():當(dāng)State對象從樹中被永久移除時調(diào)用;通常在此回調(diào)中釋放資源。

StatelessWidget


class MyStatelessWidget extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return new Container(color: const Color(0xFF2DBD3A));
  }

}

StatelessWidget的build方法通常會在以下三種情況被調(diào)用:

  • 將widget插入樹中時
  • 當(dāng)widget的父級更改其配置時
  • 當(dāng)它依賴的InheritedWidget發(fā)生變化時

StatefulWidget

StatefulWidget是有可變狀態(tài)的Widget。

  1. 在initState中創(chuàng)建資源,在dispose中銷毀,但是不依賴于InheritedWidget或者調(diào)用setState方法,這類widget基本上用在一個應(yīng)用或者頁面的root;
  2. 使用setState或者依賴于InheritedWidget,這種在營業(yè)生命周期中會被重建(rebuild)很多次。
class MyHomePage extends StatefulWidget {
  const YellowBird({ Key key }) : super(key: key);

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<YellowBird> {
  @override
  Widget build(BuildContext context) {
    return new Container(color: const Color(0xFFFFE306));
  }
}

二 基本組件

Container

Container在Flutter很常見。官方給出的簡介,是一個結(jié)合了繪制(painting)、定位(positioning)以及尺寸(sizing)widget的widget。

組成

Container的組成如下:

  • 最里層的是child元素;
  • child元素首先會被padding包著;
  • 然后添加額外的constraints限制;
  • 最后添加margin。

Container的繪制的過程如下:

  • 首先會繪制transform效果;
  • 接著繪制decoration;
  • 然后繪制child;
  • 最后繪制foregroundDecoration。

Container自身尺寸的調(diào)節(jié)分兩種情況:

  • Container在沒有子節(jié)點(diǎn)(children)的時候,會試圖去變得足夠大。除非constraints是unbounded限制,在這種情況下,Container會試圖去變得足夠小。
  • 帶子節(jié)點(diǎn)的Container,會根據(jù)子節(jié)點(diǎn)尺寸調(diào)節(jié)自身尺寸,但是Container構(gòu)造器中如果包含了width、height以及constraints,則會按照構(gòu)造器中的參數(shù)來進(jìn)行尺寸的調(diào)節(jié)。

布局行為

由于Container組合了一系列的widget,這些widget都有自己的布局行為,因此Container的布局行為有時候是比較復(fù)雜的。

一般情況下,Container會遵循如下順序去嘗試布局:

  • 對齊(alignment);
  • 調(diào)節(jié)自身尺寸適合子節(jié)點(diǎn);
  • 采用width、height以及constraints布局;
  • 擴(kuò)展自身去適應(yīng)父節(jié)點(diǎn);
  • 調(diào)節(jié)自身到足夠小。

進(jìn)一步說:

  • 如果沒有子節(jié)點(diǎn)、沒有設(shè)置width、height以及constraints,并且父節(jié)點(diǎn)沒有設(shè)置unbounded的限制,Container會將自身調(diào)整到足夠小。
  • 如果沒有子節(jié)點(diǎn)、對齊方式(alignment),但是提供了width、height或者constraints,那么Container會根據(jù)自身以及父節(jié)點(diǎn)的限制,將自身調(diào)節(jié)到足夠小。
  • 如果沒有子節(jié)點(diǎn)、width、height、constraints以及alignment,但是父節(jié)點(diǎn)提供了bounded限制,那么Container會按照父節(jié)點(diǎn)的限制,將自身調(diào)整到足夠大。
  • 如果有alignment,父節(jié)點(diǎn)提供了unbounded限制,那么Container將會調(diào)節(jié)自身尺寸來包住child;
  • 如果有alignment,并且父節(jié)點(diǎn)提供了bounded限制,那么Container會將自身調(diào)整的足夠大(在父節(jié)點(diǎn)的范圍內(nèi)),然后將child根據(jù)alignment調(diào)整位置;
  • 含有child,但是沒有width、height、constraints以及alignment,Container會將父節(jié)點(diǎn)的constraints傳遞給child,并且根據(jù)child調(diào)整自身。

另外,margin以及padding屬性也會影響到布局。

構(gòu)造方法

Container({
    Key key,
    this.alignment,
    this.padding,
    Color color,
    Decoration decoration,
    this.foregroundDecoration,
    double width,
    double height,
    BoxConstraints constraints,
    this.margin,
    this.transform,
    this.child,
  })

平時使用最多的,也就是padding、color、width、height、margin屬性。

屬性解析

alignment:控制child的對齊方式,如果container或者container父節(jié)點(diǎn)尺寸大于child的尺寸,這個屬性設(shè)置會起作用,有很多種對齊方式。

padding:decoration內(nèi)部的空白區(qū)域,如果有child的話,child位于padding內(nèi)部。padding與margin的不同之處在于,padding是包含在content內(nèi),而margin則是外部邊界,設(shè)置點(diǎn)擊事件的話,padding區(qū)域會響應(yīng),而margin區(qū)域不會響應(yīng)。

color:用來設(shè)置container背景色,如果foregroundDecoration設(shè)置的話,可能會遮蓋color效果。

decoration:繪制在child后面的裝飾,設(shè)置了decoration的話,就不能設(shè)置color屬性,否則會報錯,此時應(yīng)該在decoration中進(jìn)行顏色的設(shè)置。

foregroundDecoration:繪制在child前面的裝飾。

width:container的寬度,設(shè)置為double.infinity可以強(qiáng)制在寬度上撐滿,不設(shè)置,則根據(jù)child和父節(jié)點(diǎn)兩者一起布局。

height:container的高度,設(shè)置為double.infinity可以強(qiáng)制在高度上撐滿。

constraints:添加到child上額外的約束條件。

margin:圍繞在decoration和child之外的空白區(qū)域,不屬于內(nèi)容區(qū)域。

transform:設(shè)置container的變換矩陣,類型為Matrix4。

child:container中的內(nèi)容widget。

代碼示例
new Container(
  constraints: new BoxConstraints.expand(
    height:Theme.of(context).textTheme.display1.fontSize * 1.1 + 200.0,
  ),
  decoration: new BoxDecoration(
    border: new Border.all(width: 2.0, color: Colors.red),
    color: Colors.grey,
    borderRadius: new BorderRadius.all(new Radius.circular(20.0)),
    image: new DecorationImage(
      image: new NetworkImage('https://hosjoy-iot.oss-cn-hangzhou.aliyuncs.com/images/public/LKM.png'),
      centerSlice: new Rect.fromLTRB(270.0, 180.0, 1360.0, 730.0),
    ),
  ),
  padding: const EdgeInsets.all(8.0),
  alignment: Alignment.center,
  child: new Text('Hello World',
    style: Theme.of(context).textTheme.display1.copyWith(color: Colors.black)),
  transform: new Matrix4.rotationZ(0.3),
)

其中decoration可以設(shè)置邊框、背景色、背景圖片、圓角等屬性。對于transform這個屬性,一般不是變換的實(shí)際位置,而是變換的繪制效果,也就是說它的點(diǎn)擊以及尺寸、間距等都是按照未變換前的。

Row、Column

Row

Row.png
Row({
  Key key,
  MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
  MainAxisSize mainAxisSize = MainAxisSize.max,
  CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
  TextDirection textDirection,
  VerticalDirection verticalDirection = VerticalDirection.down,
  TextBaseline textBaseline,
  List<Widget> children = const <Widget>[],
})
header 1 header 2
MainAxisAlignment 主軸方向上的對齊方式,會對child的位置起作用,默認(rèn)是start。
MainAxisSize 在主軸方向占有空間的值,默認(rèn)是max。
CrossAxisAlignment children在交叉軸方向的對齊方式,與MainAxisAlignment略有不同
VerticalDirection children擺放順序,默認(rèn)是down。
TextBaseline 使用的TextBaseline的方式

MainAxisAlignment值:

  • center:將children放置在主軸的中心;
  • end:將children放置在主軸的末尾;
  • spaceAround:將主軸方向上的空白區(qū)域均分,使得children之間的空白區(qū)域相等,但是首尾child的空白區(qū)域?yàn)?/2;
  • spaceBetween:將主軸方向上的空白區(qū)域均分,使得children之間的空白區(qū)域相等,首尾child都靠近首尾,沒有間隙;
  • spaceEvenly:將主軸方向上的空白區(qū)域均分,使得children之間的空白區(qū)域相等,包括首尾child;
  • start:將children放置在主軸的起點(diǎn);

MainAxisSize的取值:

  • max:根據(jù)傳入的布局約束條件,最大化主軸方向的可用空間;
  • min:與max相反,是最小化主軸方向的可用空間;

CrossAxisAlignment的值:

  • baseline:在交叉軸方向,使得children的baseline對齊;
  • center:children在交叉軸上居中展示;
  • end:children在交叉軸上末尾展示;
  • start:children在交叉軸上起點(diǎn)處展示;
  • stretch:讓children填滿交叉軸方向;

VerticalDirection的值:

  • down:從top到bottom進(jìn)行布局;
  • up:從bottom到top進(jìn)行布局。

Column

Column.png

Column與Row類似只是排列方式不同,不再贅述

文本組件Text

構(gòu)造函數(shù)

const Text(
    this.data, {
    Key key,
    this.style,
    this.strutStyle,
    this.textAlign,
    this.textDirection,
    this.locale,
    this.softWrap,
    this.overflow,
    this.textScaleFactor,
    this.maxLines,
    this.semanticsLabel,
    this.textWidthBasis,
  }) 
       

       
const Text.rich(
    this.textSpan, {
    Key key,
    this.style,
    this.strutStyle,
    this.textAlign,
    this.textDirection,
    this.locale,
    this.softWrap,
    this.overflow,
    this.textScaleFactor,
    this.maxLines,
    this.semanticsLabel,
    this.textWidthBasis,
  })

text有兩個構(gòu)造函數(shù),第一個是默認(rèn),第二個是實(shí)現(xiàn)Text.rich樣式的,和 Android 中的 SpannableString 一樣,具體API屬性如下:

屬性 含義
textAlign 文本對齊方式(center居中,left左對齊,right右對齊,justfy兩端對齊)
textDirection 文本方向(ltr從左至右,rtl從右至左)
softWare 是否自動換行(true自動換行,false單行顯示,超出屏幕部分默認(rèn)截斷處理)
overflow 文字超出屏幕之后的處理方式(clip裁剪,fade漸隱,ellipsis省略號)
textScaleFactor 字體顯示倍率
maxLines 文字顯示最大行數(shù)
style 字體的樣式設(shè)置

代碼示例

 child: new Column(
        children: <Widget>[
          new Text(
            "Unit 1 Lesson 3 About animal",
            style: new TextStyle(
                fontFamily: "Round", fontSize: 20, color: Colors.white),
          ),
          Text('默認(rèn)text'),
          Padding(
            padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0),
            child: Text(
              'Flutter擁有豐富的工具和庫,可以幫助您輕松地同時在iOS和Android系統(tǒng)中實(shí)現(xiàn)您的想法和創(chuàng)意。',
              //是否自動換行 false文字不考慮容器大小,單行顯示,超出屏幕部分將默認(rèn)截斷處理
              softWrap: true,
            ),
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0),
            child: Text(
              'Flutter擁有豐富的工具和庫,可以幫助您輕松地同時在iOS和Android系統(tǒng)中實(shí)現(xiàn)您的想法和創(chuàng)意。',
              //文字超出屏幕之后的處理方式  TextOverflow.clip剪裁   TextOverflow.fade 漸隱  TextOverflow.ellipsis省略號
              overflow: TextOverflow.ellipsis,
            ),
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0),
            child: Text(
              'Flutter擁有豐富的工具和庫,可以幫助您輕松地同時在iOS和Android系統(tǒng)中實(shí)現(xiàn)您的想法和創(chuàng)意,可以幫助您輕松地同時在iOS和Android系統(tǒng)中實(shí)現(xiàn)您的想法和創(chuàng)意。',
              maxLines: 2,
              overflow: TextOverflow.ellipsis,
            ),
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0),
            child: Text(
              '文本方向 Flutter擁有豐富的工具和庫,可以幫助您輕松地同時在iOS和Android系統(tǒng)中實(shí)現(xiàn)您的想法和創(chuàng)意。',
              //TextDirection.ltr從左至右,TextDirection.rtl從右至左
              textDirection: TextDirection.rtl,
            ),
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0),
            child: Text(
              '文本對齊方式 Flutter擁有豐富的工具和庫,可以幫助您輕松地同時在iOS和Android系統(tǒng)中實(shí)現(xiàn)您的想法和創(chuàng)意。',
              //TextAlign.left左對齊,TextAlign.right右對齊,TextAlign.center居中對齊,TextAlign.justfy兩端對齊
              textAlign: TextAlign.center,
            ),
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0),
            child: Text(
              '設(shè)置顏色和大小',
              style: TextStyle(
                color: const Color(0xfff2c222),
                fontSize: 20,
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0),
            child: Text(
              '設(shè)置粗細(xì)和斜體',
              style: TextStyle(
                //字體粗細(xì),粗體和正常
                fontWeight: FontWeight.bold,
                //文字樣式,斜體和正常
                fontStyle: FontStyle.italic,
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0),
            child: Text(
              '設(shè)置文字裝飾',
              style: TextStyle(
                //none無文字裝飾,lineThrough刪除線,overline文字上面顯示線,underline文字下面顯示線
                  decoration: TextDecoration.underline,
                  decorationColor: Colors.blue,
                  decorationStyle: TextDecorationStyle.wavy
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0),
            child: Text(
              '單詞間隙 hello world',
              style: TextStyle(
                wordSpacing: 10.0,
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 0.0),
            child: Text(
              '字母間隙 hello world',
              style: TextStyle(
                letterSpacing: 10.0,
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0),
            child: GestureDetector(
              onTap: () {
                print("點(diǎn)擊了按鈕");
              },
              child: Text(
                '設(shè)置文字點(diǎn)擊事件',
                style: TextStyle(
                  color: Colors.blue,
                  fontWeight: FontWeight.bold,
                  fontStyle: FontStyle.italic,
                ),
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(0.0, 10.0, 0.0, 0.0),
            child: Text.rich(
              new TextSpan(
                  text: 'Text.rich',
                  style: new TextStyle(
                      color: Colors.blueAccent,
                      fontSize: 10,
                      decoration: TextDecoration.none),
                  children: <TextSpan>[
                    new TextSpan(
                        text: '拼接測試1',
                        style: new TextStyle(
                            color: Colors.blue,
                            fontSize: 14,
                            decoration: TextDecoration.none)),
                    new TextSpan(
                        text: '拼接測試2',
                        style: new TextStyle(
                            color: Colors.black,
                            fontSize: 18,
                            decoration: TextDecoration.none)),
                    new TextSpan(
                        text: '拼接測試3',
                        style: new TextStyle(
                            color: Colors.red,
                            fontSize: 22,
                            decoration: TextDecoration.none)),
                    new TextSpan(
                        text: '拼接測試4',
                        style: new TextStyle(
                            color: Colors.grey,
                            fontSize: 26,
                            decoration: TextDecoration.none)),
                  ]),
            ),
          )

        ],

      ),
text.png

圖片組件Image

構(gòu)造方法

Image({
    Key key,
    @required this.image,
    this.semanticLabel,
    this.excludeFromSemantics = false,
    this.width,
    this.height,
    this.color,
    this.colorBlendMode,
    this.fit,
    this.alignment = Alignment.center,
    this.repeat = ImageRepeat.noRepeat,
    this.centerSlice,
    this.matchTextDirection = false,
    this.gaplessPlayback = false,
    this.filterQuality = FilterQuality.low,
  })
API 屬性
BoxFit.contain 顯示整張圖片,按照原始比例縮放顯示
BoxFit.fill 顯示整張圖片,拉伸填充全部可顯示區(qū)域
BoxFit.cover 按照原始比例縮放,可能裁剪,填滿可顯示區(qū)域
BoxFit.fitHeight 按照原始比例縮放,可能裁剪,高度優(yōu)先填滿
BoxFit.fitWidth 按照原始比例縮放,可能裁剪寬度優(yōu)先填滿
BoxFit.none 圖片居中顯示,不縮放原圖,可能被裁剪
BoxFit.scaleDown 顯示整張圖片,只能縮小或者原圖顯示
colorBlendMode

圖片顏色混合處理,篇幅有限,有興趣的可以點(diǎn)擊鏈接查看

按鈕類組件(IconButton、RaisedButton)

構(gòu)造方法

const IconButton({
    Key key,
    this.iconSize = 24.0,
    this.padding = const EdgeInsets.all(8.0),
    this.alignment = Alignment.center,
    @required this.icon,
    this.color,
    this.highlightColor,
    this.splashColor,
    this.disabledColor,
    @required this.onPressed,
    this.tooltip
  }) : assert(iconSize != null),
       assert(padding != null),
       assert(alignment != null),
       assert(icon != null),
       super(key: key);

屬性 含義
highlightColor 按鈕處于按下狀態(tài)時按鈕的輔助顏色。
splashColor 按鈕處于按下狀態(tài)時按鈕的主要顏色。
disabledColor 圖標(biāo)組件禁用的顏色,默認(rèn)為主題里的禁用顏色
onPressed 點(diǎn)擊或以其他方式激活按鈕時調(diào)用的回調(diào)。如果將其設(shè)置為null,則將禁用該按鈕。
tooltip 描述按下按鈕時將發(fā)生的操作的文本。

代碼示例

new IconButton(
            padding: EdgeInsets.zero,
            iconSize: 60.0,
            icon: new Image.asset("assets/images/share_wechat.png"),
            onPressed: () {
              print("share to wechat");
            }),
imageButton.png

列表類組件ListView

ListView({
    Key key,
    Axis scrollDirection = Axis.vertical,
    bool reverse = false,
    ScrollController controller,
    bool primary,
    ScrollPhysics physics,
    bool shrinkWrap = false,
    EdgeInsetsGeometry padding,
    this.itemExtent,
    bool addAutomaticKeepAlives = true,
    bool addRepaintBoundaries = true,
    bool addSemanticIndexes = true,
    double cacheExtent,
    List<Widget> children = const <Widget>[],
    int semanticChildCount,
    DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  }) 
屬性 含義
reverse 是否反向滾動
controller 滾動控制器
primary 是否是與父級PrimaryScrollController關(guān)聯(lián)的主滾動視圖。如果primary為true,controller必須設(shè)置
shrinkWrap 滾動方向上的滾動視圖的范圍是否應(yīng)由所查看的內(nèi)容決定。
itemExtent 子元素長度
physics 列表滾動至邊緣后繼續(xù)拖動的物理效果
cacheExtent 預(yù)渲染區(qū)域長度

代碼示例

 child: new ListView.builder(
        padding: new EdgeInsets.all(30.0),
        itemExtent: 50.0,
        itemBuilder: (BuildContext context, int index) {
          return new Text("Hosjoy $index");
        },
      ),
listView.png

網(wǎng)各類組件GridView

構(gòu)造方法

  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 <Widget>[],
    int semanticChildCount,
    DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  })

gridView的屬性可以參考ListView,下面列舉GrideView特有的屬性

屬性 含義
mainAxisSpacing itme的水平距離
crossAxisSpacing item的垂直距離
childAspectRatio item的寬高比
crossAxisCount 每行的item個數(shù)

代碼示例

GridView.count(padding: const EdgeInsets.all(20.0),
        crossAxisSpacing: 10.0,
        crossAxisCount: 3,
        children: <Widget>[
          const Text('Hosjoy'),
          new Image.network('https://hosjoy-iot.oss-cn-hangzhou.aliyuncs.com/images/public/LKM.png',fit: BoxFit.cover),
          const Text('Hosjoy'),
          const Text('Hosjoy'),
          new Image.network('https://hosjoy-iot.oss-cn-hangzhou.aliyuncs.com/images/public/LKM.png',fit: BoxFit.cover),
          const Text('Hosjoy'),
          const Text('Hosjoy'),
          new Image.network('https://hosjoy-iot.oss-cn-hangzhou.aliyuncs.com/images/public/LKM.png',fit: BoxFit.cover),
          new Image.network('https://hosjoy-iot.oss-cn-hangzhou.aliyuncs.com/images/public/LKM.png',fit: BoxFit.cover),
        ],
      ),
GridView.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容