Flutter第3天--基礎控件(上)

Flutter七日遊第三天:2018-12-18 天氣:晴朗

零、前言

浪了兩天,Dart語法基本上熟悉了,繪圖也不怕了,如今進入正軌,繼續浪~
今天來學些枯燥的東西了--基礎控件,戒驕戒躁,基礎仍是要好好掌握。
本文目的在於儘量看清控件的全局(細枝末節點到爲止),詳細用法等佈局實戰再細說吧
本文能用圖的,儘可能不用字(看完你可能會以爲我腦洞有點大),廢話很少說,進入今天的內容css


1、Widget簡入

Widget:[小器具,裝飾品,窗口小部件],之後簡稱:控件
下面看一下Widget樹:(只延伸到下代)html

Widget樹.png


1.StatelessWidgetStatefulWidget

目前出如今我眼前的只這有兩個,因此先只看這兩個:git

StatelessWidget:源碼第一句話:
---->A widget that does not require mutable state.
---->一個不須要變更狀態的控件

StatefulWidget :源碼第一句話:
---->A widget that has mutable state.
---->一個可變更狀態的控件
複製代碼

2.StatelessWidget一共就有三個方法:

StatelessWidget.png

-------->[構造方法,須要一個key,並且老爸已經給他了]----
/// Initializes [key] for subclasses.
const StatelessWidget({ Key key }) : super(key: key);

-------->[createElement方法複寫Widget方法,使用StatelessElement--tag1--自給自足]
/// It is uncommon for subclasses to override this method.
//子類重寫此方法是不常見的。----因此就不要沒事找事了
StatelessElement createElement() => StatelessElement(this);

--tag1-->[StatelessElement,接收一個StatelessWidget]
/// An [Element] that uses a [StatelessWidget] as its configuration.
class StatelessElement extends ComponentElement {
 /// Creates an element that uses the given widget as its configuration.
  StatelessElement(StatelessWidget widget) : super(widget);
  
-------->[使用如今要關注的只有:build方法--]
/// Describes the part of the user interface represented by this widget.  
//描述此控件呈如今用戶界面上的部分
  @protected
  Widget build(BuildContext context);//空實現
複製代碼

3.初始項目看StatelessWidget:

StatelessWidget映入眼簾,可見該類內部必定有一個build方法返回一個Widgetgithub

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.lightBlue,
      ),
      home:MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

//不難看出MaterialApp是一個Widget,並且至少有title,theme,home三個屬性
並且home傳入的是一個Widget
複製代碼

4.恭喜達成成就:Widget源碼偷窺者, 成就獎勵:三張卡片:

卡片初始屬性:見白框(PS:屬性會隨着你的閱歷變多哦)編程

- - -

2、Flutter卡牌遊戲Start

接下來會列出一長串屬性,並挑選些簡單的屬性測試一下
若是你以爲及其無聊,列屬性的地方能夠跳過,基本上每三個作一個小測試canvas

1:MaterialApp--材料App

An application that uses material design.源碼如是說:一個使用材料設計的App
繼承自StatefulWidget,字段蠻多的,先列一下,看看如今用到的,其餘的用到再說吧。數組

class MaterialApp extends StatefulWidget 

    this.navigatorKey,
    this.home,//--->tag1<---
    this.routes = const <String, WidgetBuilder>{},
    this.initialRoute,
    this.onGenerateRoute,
    this.onUnknownRoute,
    this.navigatorObservers = const <NavigatorObserver>[],
    this.builder,
    this.title = '',//--->tag2<---
    this.onGenerateTitle,
    this.color,
    this.theme,//--->tag3<---
    this.locale,
    this.localizationsDelegates,
    this.localeListResolutionCallback,
    this.localeResolutionCallback,
    this.supportedLocales = const <Locale>[Locale('en', 'US')],
    this.debugShowMaterialGrid = false,
    this.showPerformanceOverlay = false,
    this.checkerboardRasterCacheImages = false,
    this.checkerboardOffscreenLayers = false,
    this.showSemanticsDebugger = false,
    this.debugShowCheckedModeBanner = true,

//--->tag1<---[title是個字符串]----
/// This value is passed unmodified to [WidgetsApp.title].
final String title;

//--->tag2<---[theme是個ThemeData對象:保存材料設計主題的顏色和版式值]----
/// The colors to use for the application's widgets. final ThemeData theme; //--->tag3<---[home是個Widget對象]---- /// {@macro flutter.widgets.widgetsApp.home} final Widget home; 複製代碼

2.Scaffold--腳手架

什麼是腳手架,大概就是這個感受吧,也就是輔助腳手的工具,方便施工bash

腳手架.png

PreferredSizeWidget             this.appBar,
Widget                          this.body,
Widget                          this.floatingActionButton,
FloatingActionButtonLocation    this.floatingActionButtonLocation,
FloatingActionButtonAnimator    this.floatingActionButtonAnimator,
List<Widget>                    this.persistentFooterButtons,
Widget                          this.drawer,
Widget                          this.endDrawer,
Widget                          this.bottomNavigationBar,
Widget                          this.bottomSheet,
Color                           this.backgroundColor,
bool                            this.resizeToAvoidBottomPadding = true,
bool                            this.primary = true,
複製代碼

3:AppBar--App的Bar

就像安卓的ToolBar同樣的控件微信

Widget                  this.leading,
bool                    this.automaticallyImplyLeading = true,
Widget                  this.title,
List<Widget>            this.actions,
Widget                  this.flexibleSpace,
PreferredSizeWidget     this.bottom,
double                  this.elevation = 4.0,
Color                   this.backgroundColor,
Brightness              this.brightness,
IconThemeData           this.iconTheme,
TextTheme               this.textTheme,
bool                    this.primary = true,
bool                    this.centerTitle,
double                  this.titleSpacing = NavigationToolbar.kMiddleSpacing,
double                  this.toolbarOpacity = 1.0,
double                  this.bottomOpacity = 1.0,
複製代碼

新手任務1:能力小測試

測試.png

MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.lightBlue,
        ),
        home: Scaffold(
            appBar: AppBar(
                title: Text("張風捷特烈"),//標題
                backgroundColor: Color(0xffcbf231), //背景色
                elevation: 12,//陰影
                centerTitle: true,
                toolbarOpacity: .4)//透明度
        ));
複製代碼
新手任務完成,獎勵卡片:歡迎繼續冒險
- - -

4:Text--文字
const Text(this.data, {
TextStyle           this.style,
TextAlign           this.textAlign,
TextDirection       this.textDirection,
Locale              this.locale,
bool                this.softWrap,
TextOverflow        this.overflow,
double              this.textScaleFactor,
int                 this.maxLines,
String              this.semanticsLabel,

  /// Creates a text widget with a [TextSpan].
  const Text.rich(this.textSpan, {
        //同上
  })
複製代碼
//---->[TextStyle]----------------
bool                this.inherit = true,
Color               this.color,
double              this.fontSize,
FontWeight          this.fontWeight,
FontStyle           this.fontStyle,
double              this.letterSpacing,
double              this.wordSpacing,
TextBaseline        this.textBaseline,
double              this.height,
Locale              this.locale,
Paint               this.foreground,
Paint               this.background,
List<ui.Shadow>     this.shadows,
TextDecoration      this.decoration,
Color               this.decorationColor,
TextDecorationStyle this.decorationStyle,
String              this.debugLabel,
String              String fontFamily,

//---->[TextAlign]----------------
enum TextAlign {
  left,right,center,justify,start,end,
}

//---->[TextOverflow]----------------
enum TextOverflow {
  clip,fade,ellipsis,
}
複製代碼

5.FloatingActionButton--浮動動做按鈕
Widget                  this.child,
String                  this.tooltip,
Color                   this.foregroundColor,
Color                   this.backgroundColor,
Object                  this.heroTag = const _DefaultHeroTag(),
double                  this.elevation = 6.0,
double                  this.highlightElevation = 12.0,
VoidCallback            @required this.onPressed,
bool                    this.mini = false,
ShapeBorder             this.shape = const CircleBorder(),
Clip                    this.clipBehavior = Clip.none,
MaterialTapTargetSize   this.materialTapTargetSize,
bool                    this.isExtended = false,
複製代碼
6.Icon--圖標
double          this.size,
Color           this.color,
String          this.semanticLabel,------This label does not show in the UI.
TextDirection   this.textDirection,
複製代碼
新手任務2:

Text

FloatingActionButton.png

body: Text(
            "一簫一劍生平意,負盡狂名十五年",
            maxLines: 1,
            overflow: TextOverflow.fade,
            style: TextStyle(
                color: Colors.blue,
                fontSize: 20,
                letterSpacing: 10,
                fontWeight: FontWeight.bold,
                background: Paint()..color = Colors.amberAccent),
          ),
          floatingActionButton: FloatingActionButton(
            backgroundColor: Colors.deepOrangeAccent,
            elevation: 12,
            highlightElevation: 24,
            onPressed: () {},
            tooltip: 'Increment',
            child: Icon(Icons.add,size: 40,color: Colors.white,semanticLabel:"toly"),
          ),
複製代碼

3、基礎控件點將臺(1)

以上6張卡片是初始項目中的控件,經過新手任務基本上更加熟悉了一些
Flutter還有哪些控件,建議看一下Flutter中文網,羅列的挺好的,下面一塊兒學習一下
(PS:看了一下,真是多如雞毛...嚇得我不知從何入手)app

所謂`打蛇打七寸,擒賊先擒王`,小兵以後再收拾  
經過Android和html+css,我領悟到,對於界面設計者而言,佈局是相當重要的,因此先看容器
複製代碼
1.Layout佈局容器之Row+Column--行+列

Row和Column.png


1.1:Row的基礎認知
---->[源碼註釋第一句]-----------------------------
A widget that displays its children in a horizontal array.
一個以水平數組的形式顯示其子部件的Widget。

 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>[],
複製代碼
1.2:基本使用

children看來是一個Widget數組,想一想也不難理解,畢竟作大哥的,固然要有很多小弟啦
注:爲了方便修改,如下代碼把Scaffold的body屬性值抽成變量使用

var row_test = Row(
  children: <Widget>[
    Text('絕域從軍計惘然,,'),
    Text('東南幽恨滿詞箋。'),
    Text('一簫一劍生平意,'),
    Text('負盡狂名十五年。'),
  ],
);
複製代碼

越界提醒.png

能夠看出越界有提醒,感受蠻有心的,水平排列沒毛病


1.3.Column:用法基本上差很少
---->[源碼註釋第一句]-----------------------------
 A widget that displays its children in a vertical array.
一個以豎直數組的形式顯示其子部件的Widget。

Column({
    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>[],
複製代碼
1.4.Column基本使用
var row_column = Column(
  children: <Widget>[
    Text('絕域從軍計惘然,,'),
    Text('東南幽恨滿詞箋。'),
    Text('一簫一劍生平意,'),
    Text('負盡狂名十五年。'),
  ],
);
複製代碼

Column.png


恭喜完成成就:佈局菜鳥---獎勵卡片:
- - -

恭喜解鎖新卡片:Expanded,快去用用吧
Expanded意思是:使…伸展,看到下面的圖,你應該就會明白

var row_test = Row(
  children: <Widget>[
    Expanded(
      child:Text('絕域從軍計惘然,'),
    ),
    Expanded(
      child:Text('東南幽恨滿詞箋。'),
    ),
    Expanded(
      child:Text('一簫一劍生平意,'),
    ),
    Expanded(
      child:Text('負盡狂名十五年。'),
    ),
  ],
);
複製代碼

Expanded.png


2.Container--容器

能夠理解爲Android中的View,更像html中的div
Container是一個沒有狀態的控件

Container.png


2.1:源碼小窺
---->[源碼註釋第一句]-----------------------------
A convenience widget that combines common painting, positioning, and sizing widgets.
一個方便的widget,它組合了常見的painting、positioning和sizing 控件。

Color                   color,
double                  width,
double                  height,
Widget                  this.child,
EdgeInsetsGeometry      this.margin,
EdgeInsetsGeometry      this.padding,
AlignmentGeometry       this.alignment,
Decoration              Decoration decoration,
Decoration              this.foregroundDecoration,
BoxConstraints          BoxConstraints constraints,
Matrix4                 this.transform,
複製代碼

2.2:簡單使用:

[插曲]這裏分享一個點:當看到一個新的東西應該怎麼辦?

好比`margin`,看到`EdgeInsetsGeometry`個人心情是一臉懵X,不該該是數字嗎?
進源碼:`abstract class EdgeInsetsGeometry {`,抽象的,找他兒子去,
AndroidStudio中按`Ctrl+H`能夠查看繼承樹,而後就看到了EdgeInsets.fromLTRB
這樣Flutter的margin就和你的知識庫中的margin進行了鏈接,你就會用了

class EdgeInsets extends EdgeInsetsGeometry {
  const EdgeInsets.fromLTRB(this.left, this.top, this.right, this.bottom);
  const EdgeInsets.all(double value)
      : left = value, top = value, right = value, bottom = value;

新事物每每都與舊事物有聯繫,學習新事物最好快速找到它與你知識庫中舊事物的聯繫,
聯繫的多少取決於你知識庫中內容的多少,鏈接得越多,你會越快或越能掌握舊事物 
複製代碼
var container_test = Container(
  color: Color.fromARGB(100, 81, 211, 253),
  height: 100,
  width: 200,
  child: Text("張風捷特烈"),
  margin: EdgeInsets.fromLTRB(5, 10, 15, 20),
  padding:  EdgeInsets.all(40),
);
複製代碼

padding和margin簡稱pm,左圖是上面代碼沒有pm時,右圖是有pm時

Container測試.png


恭喜達成成就:Container使用者--卡牌獎勵:
- - -

NPC:恭喜解鎖兩張輔助卡PaddingCenter,快來測試一下吧
這兩個沒什麼好說的,顧圖思義,看圖吧

var padding_test = Container(
  color: Color.fromARGB(100, 81, 211, 253),
  height: 150,
  width: 250,
  child: Padding(
    padding: EdgeInsets.all(10),
    child: Text("張風捷特烈"),
  ),
);


var center_test = Container(
  color: Color.fromARGB(100, 81, 211, 253),
  height: 150,
  width: 250,
  child: Center(
    child: Text("張風捷特烈"),
  ),
);
複製代碼

Center和Padding.png


3.Stack -- 堆疊

第一反應:棧?有道了一下,有堆疊的意思

---->[源碼註釋第一句]-----------------------------
A widget that positions its children relative to the edges of its box.
一個相對於它的框的邊緣來定位它的子部件的Widget。

    this.alignment = AlignmentDirectional.topStart,
    this.textDirection,
    this.fit = StackFit.loose,
    this.overflow = Overflow.clip,
    List<Widget> children = const <Widget>[],
    
複製代碼

觸發新手任務3,並觸發局部Widget樹,系統贈送卡牌:

看一下Widget樹.png

- - -

請完成下面佈局:

新手任務3.png

var stack_test = Container(
    color: Color.fromARGB(100, 81, 211, 253),
    height: 150,
    width: 250,
    child: Stack(
      alignment: Alignment.centerLeft,
      children: <Widget>[
        Text('絕域從軍計惘然,,'),
        Align(
          alignment: Alignment.topRight,
          widthFactor: 1.5,
          child: Card(
              elevation: 10, color: Color(0xffffffff), child: Text('東南幽恨滿詞箋。')),
        ),
        Text('一簫一劍生平意,'),
        Text('負盡狂名十五年。'),
      ],
    ));
複製代碼

如今對Stack有點感受了吧,它像FramLayout同樣會疊合控件,
而且alignment還能夠肯定Stack自身相對於老爸的位置
Align也有alignment,不過能有一個孩子,Card我最喜歡了
這裏mark一下Card裏的ShapeBorder shape,源碼粗略看了一下,可能挺好玩,今天主看控件


4.IndexedStack--定索引顯示

按照索引來顯示堆疊容器中的控件,挺好玩的

看一下Widget樹2.png

IndexedStack.png

var index_stack_test = Container(
    color: Color.fromARGB(100, 81, 211, 253),
    height: 150,
    width: 250,
    child: IndexedStack(
      index:3,
      alignment: Alignment.centerLeft,
      children: <Widget>[
        Text('絕域從軍計惘然,'),
        Align(
          alignment: Alignment.topRight,
          widthFactor: 1.5,
          child: Card(
              elevation: 10, color: Color(0xffffffff), child: Text('東南幽恨滿詞箋。')),
        ),
        Text('一簫一劍生平意,'),
        Text('負盡狂名十五年。'),
      ],
    ));

複製代碼

5.Transform--變換

transform屬性的Matrix4有機會確定好好分析分析,mark一下
Matrix4.rotationZ傳入的是弧度制的度數,佩服佩服

Transform(
    origin: Offset(0, 150),
    transform: Matrix4.rotationZ(3.1415 / 4),
    child: //同上面的Container,挺長的,不貼了
    )
複製代碼

Transform.png


6.Offstage--顯隱控制

負盡狂名十五年用Offstage包裹一下,offstage爲true--隱藏,爲false--顯示
感受應該挺好用,簡潔,明瞭,人狠話很少。

Offstage(
    offstage: false,
    child: Text('負盡狂名十五年。'),
),
複製代碼
恭喜得到成就:佈局小新手 :獎勵卡牌:
- - -

3、基礎控件點將臺之--三大戰力

隱藏劇情觸發:
NPC:傳說有三條惡龍盤踞在佈局深處,爲禍人間,勇士們,準備好了嗎?

看一下Widget樹3.png

1.表格--Table
1.1:屬性一覽
this.children = const <TableRow>[],
    this.columnWidths,
    this.defaultColumnWidth = const FlexColumnWidth(1.0),
    this.textDirection,
    this.border,
    this.defaultVerticalAlignment = TableCellVerticalAlignment.top,
    this.textBaseline,
複製代碼

1.2:新手任務4:完成下面表格

表格.png

代碼實現:
columnWidths:能夠指定每列的寬度
border:邊線的樣式
children:經過TableRow來顯示一行

var table_test = Table(
  columnWidths: const <int, TableColumnWidth>{
    0: FixedColumnWidth(60.0),
    1: FixedColumnWidth(100.0),
    2: FixedColumnWidth(100.0),
    3: FixedColumnWidth(80.0),
  },
  defaultVerticalAlignment: TableCellVerticalAlignment.middle,
  border:
      TableBorder.all(color: Color(0xff16DAF1), width: 1.0, style: BorderStyle.solid),
  children: const <TableRow>[
    TableRow(
      children: <Widget>[
        Center(child: Text('姓名')),
        Center(child: Text('年齡')),
        Center(child: Text('稱號')),
        Center(child: Text('武器')),
      ],
    ),
    TableRow(
      children: <Widget>[
        Text('捷特'),
        Text('24'),
        Text('風神'),
        Text('黑風劍'),
      ],
    ),
    TableRow(
      children: <Widget>[
        Text('巫纓'),
        Text('23'),
        Text('百里巫纓'),
        Text('百里弓'),
      ],
    ),
    TableRow(
      children: <Widget>[
        Text('龍少'),
        Text('23'),
        Text('控尊'),
        Text('控尊戒'),
      ],
    ),
  ],
);
複製代碼

2.流動容器 --Flow:
2.1:屬性一覽

屬性很簡潔,可是:FlowDelegate夠熬一碗粥的

FlowDelegate @required this.delegate,
List<Widget> children = const <Widget>[],
複製代碼

2.2:新手任務5:用完Flow成下面佈局

簡單分析一下:隨機顏色,隨機長度,到尾部不夠就換行

flow.png

代碼實現:從網上找了一個FlowDelegate的實現類
核心就是根據位置能夠本身繪製孩子的位置(吐槽:源碼了居然沒有實現類,給一個也好啊...)

class MarginFlowDelegate extends FlowDelegate {
  EdgeInsets _margin = EdgeInsets.zero;//成員變量_margin
  MarginFlowDelegate(this._margin); //構造函數
  @override//繪製孩子的方法
  void paintChildren(FlowPaintingContext context) {
    var offsetX = _margin.left;
    var offsetY = _margin.top;
    for (int i = 0; i < context.childCount; i++) {
      var w = context.getChildSize(i).width + offsetX + _margin.right;
      if (w < context.size.width) {
        context.paintChild(i, transform: new Matrix4.translationValues(offsetX, offsetY, 0.0));
        offsetX = w + _margin.left;
      } else {
        offsetX = _margin.left;
        offsetY += context.getChildSize(i).height + _margin.top + _margin.bottom;
        context.paintChild(i,transform: new Matrix4.translationValues(offsetX, offsetY, 0.0));
        offsetX += context.getChildSize(i).width + _margin.left + _margin.right;
      }
    }
  }
複製代碼

動態生成Widget數組(可別傻傻的cv,60個Container)

formColorList(int count) {
  var random = new Random();
  var li = <Widget>[];

  for (int i = 0; i < count; i++) {
    li.add(new Container(
      width: 100 * (random.nextDouble() + 0.3),
      height: 30,
      color: randomRGB(),
    ));
  }
  return li;
}
複製代碼

用起來卻是簡單:

var flow_test = Flow(
    delegate: MarginFlowDelegate(EdgeInsets.all(5)),
    children: formColorList(60));
複製代碼

3.包裹--Warp
3.1:簡單認識:

這東西和css的flex有九分類似,還好我flex佈局玩的挺好:有興趣的可看這裏
Flow用起來麻煩不少,但可控制,靈活性更好,若是不是什麼逆天改命的佈局,Warp應該夠了

Wrap({
    Key key,
    this.direction = Axis.horizontal,
    this.alignment = WrapAlignment.start,
    this.spacing = 0.0,
    this.runAlignment = WrapAlignment.start,
    this.runSpacing = 0.0,
    this.crossAxisAlignment = WrapCrossAlignment.start,
    this.textDirection,
    this.verticalDirection = VerticalDirection.down,
    List<Widget> children = const <Widget>[],
  }) 
複製代碼
direction

方向.png


3.2:新手任務6-1

新手任務6-1.png

var wrap_test = Wrap(
    spacing: 8.0, // 列間距
    runSpacing: 4.0, //行間距
    direction:Axis.vertical ,
    crossAxisAlignment:WrapCrossAlignment.center,
    children: formColorList(50));
複製代碼

3.3:新手任務6-2

新手任務7.png

var wrap_test = Wrap(
    spacing: 8.0, // 列間距
    runSpacing: 4.0, //行間距
    direction:Axis.horizontal ,
    alignment:WrapAlignment.spaceBetween,
    children: formColorList(50));
複製代碼
duang,三大戰力倒下,恭喜得到稱號:佈局勇士,收穫三張傳說級卡片:
- - -

3、基礎控件點將臺之--列表

NPC:好吧,我編不下去了...你們加油!

看一下Widget樹4.png


1.老夥伴:ListView

這裏先簡單看一下效果,明天根據例子來詳細分析具體用法
ListView,單獨能夠用,傳入一個Widget數組,批量生產ListView.builder簡潔些

ListView.builder({
    Key key,
    Axis scrollDirection = Axis.vertical,
    bool reverse = false,
    ScrollController controller,
    bool primary,
    ScrollPhysics physics,
    bool shrinkWrap = false,
    EdgeInsetsGeometry padding,
    this.itemExtent,
    @required IndexedWidgetBuilder itemBuilder,
    int itemCount,
    bool addAutomaticKeepAlives = true,
    bool addRepaintBoundaries = true,
    bool addSemanticIndexes = true,
    double cacheExtent,
    int semanticChildCount,
複製代碼

豎直 水平
//豎直
var list_view_test = ListView.builder(
  itemCount: 20,
  padding: EdgeInsets.all(8.0),
  itemExtent: 60.0,
  itemBuilder: (BuildContext context, int index) {
    return Card(
      child: Center(child: Text('toly $index')),
    );
  },
);

//水平
var list_view_test = ListView.builder(
  itemCount: 20,
  padding: EdgeInsets.all(8.0),
  scrollDirection:Axis.horizontal,
  itemExtent: 60.0,
  itemBuilder: (BuildContext context, int index) {
    return Card(
      child: Center(child: Text('toly $index')),
    );
  },
);

複製代碼

2--老夥伴:GridView
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,
複製代碼

水平GridView 豎直GridView
//豎直GridView
var grid_view_test = GridView.count(
  crossAxisCount: 4,
  children: List.generate(
    100,
    (index) {
      return  Card(
        child: Center(child: Text('toly $index')),
      );
    },
  ),
);

//水平GridView
var grid_view_test = GridView.count(
  crossAxisCount: 4,
  scrollDirection:Axis.horizontal,
  children: List.generate(
    100,
    (index) {
      return  Card(
        child: Center(child: Text('toly $index')),
      );
    },
  ),
);

複製代碼

3.軸列容器--ListBody(我本身取的名字)

好吧,被它的名字騙了,和ListView並無太大的關係,也就是個多孩子的容器
優勢在於在指定軸上尺寸正常,另外一軸上會被拉伸,見圖:

A widget that arranges its children sequentially along a given axis,
forcing them to the dimension of the parent in the other axis.
一個widget,它按照給定的軸順序排列它的子部件,並迫使它們位於另外一個軸上的父軸的維度。


ListBody({
    Key key,
    this.mainAxis = Axis.vertical,
    this.reverse = false,
    List<Widget> children = const <Widget>[],
複製代碼

水平定 豎直定
//豎直定
var list_body_test = Column(
  children: <Widget>[
    ListBody(
      mainAxis: Axis.vertical,
      reverse: false,
      children: formColorList(5)
    )],
);

//水平定
var list_body_test = Row(
  children: <Widget>[
    ListBody(
      mainAxis: Axis.horizontal,
      reverse: false,
      children: formColorList(5)
    )],
);

複製代碼
好了,又到三局一度的髮卡時間了

未精煉的傳說級卡片,更多屬性加成,戰士們,去精煉吧

- - -

4、容器掃個尾:

1.Baseline

將文字按照基線對齊(由於比較好看)--baseline越大,距離頂端越遠

Baseline.png

const Baseline({
    Key key,
    @required this.baseline,
    @required this.baselineType,
    Widget child
複製代碼

formTextList(int count) {
  var random = new Random();
  var li = <Widget>[];

  for (int i = 0; i < count; i++) {
    li.add(new Baseline(
      baselineType: TextBaseline.alphabetic,
      child: new Text('Toly',
        style: new TextStyle(
          fontSize: 20.0 + random.nextInt(40),
          textBaseline: TextBaseline.alphabetic,
        ),
      ),
      baseline: 80,
    ));
  }
  return li;
}

var base_line_test = new Row(
  children: formTextList(5),
);
複製代碼

2.FractionallySizedBox

這個挺有意思,兒子隨爺爺,父親(FractionallySizedBox)中間倒把手
能夠實現爺爺和孫子之間的尺寸比例聯繫

const FractionallySizedBox({
    Key key,
    this.alignment = Alignment.center,
    this.widthFactor,
    this.heightFactor,
    Widget child,
複製代碼

FractionallySizedBox測試.png

var fsb_test = new Container(
  color: Colors.blue,
  height: 150.0,
  width: 150.0,
  child: new FractionallySizedBox(
    alignment: Alignment.bottomCenter,
    widthFactor: 1.5,
    heightFactor: 0.5,
    child: new Container(
      color: Colors.red,
    ),
  ),
);
複製代碼

3.AspectRatio

就是設定一個定比例的容器width/height=aspectRatio

const AspectRatio({
    Key key,
    @required this.aspectRatio,
    Widget child
複製代碼

AspectRatio測試.png

var aspectratio_test = new Container(
  width: 200.0,
  child: new AspectRatio(
    aspectRatio: 1.5,
    child: new Container(
      color: Colors.red,
    ),
  ),
);
複製代碼

恭喜得到稱號:佈局學徒 ,獎勵卡片
- - -

還剩幾個Box,明天寫幾個佈局例子順帶講一下,反正每一個新控件都會發張卡
最後把卡片總結起來,看看能不能湊夠兩幅撲克牌...打印出來當撲克牌打,還怕Flutter控件學不會?
好了,今天就到這裏,腦細胞死很多,趕快看幾集動漫補補腦。


5、總結一下mark的點:

//第一天:
3.如今焦點應該匯聚在StatefulWidget身上,不少地方都出現了,mark一下
---StatefulWidget是Widget的一個子類,是具備狀態的控件,可謂元老級別

4.canvas居然沒辦法畫文字,這不科學,mark一下
---保持mark

//第三天:
1.這裏mark一下Card裏的ShapeBorder shape,源碼粗略看了一下,可能挺好玩,今天主看控件
---保持mark

2.transform屬性的Matrix4有機會確定好好分析分析,mark一下
---保持mark
複製代碼

後記:捷文規範

1.本文成長記錄及勘誤表
項目源碼 日期 備註
V0.1-github 2018-12-18 Flutter第3天--基礎控件(上)
2.更多關於我
筆名 QQ 微信 愛好
張風捷特烈 1981462002 zdl1994328 語言
個人github 個人簡書 個人掘金 我的網站
3.聲明

1----本文由張風捷特烈原創,轉載請註明
2----歡迎廣大編程愛好者共同交流
3----我的能力有限,若有不正之處歡迎你們批評指證,一定虛心改正
4----看到這裏,我在此感謝你的喜歡與支持


icon_wx_200.png
相關文章
相關標籤/搜索