flutter基礎名詞和簡單代碼案例

字號+ 編輯: 国内TP粉 修訂: 种花家 來源: 本站原创 2023-09-11 我要說兩句(0)

flutter在慕課網上的一篇筆記。

StatefulWidget表示爲:帶狀態會變化的組件

StatelessWidget表示爲:無狀態不變化的組件


Hello World

敲一個簡單的Hello World界面:

import 'package:flutter/material.dart';

void main()=>runApp(MyApp());

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Hello World'),
        ),
        body: Center(
          child: Text('Hello World!'),
        ),
      ),
    );
  }
}

上述代碼中,

MyApp是我們自定義的一個類, 繼承StatelessWidget代表它是靜態組件, 這個靜態組件類内部已經有build(BuildContext context)這個方法, 需要重寫, 所以用到了@override這種dart寫法。

import引入到的material.dart是谷歌研發的材質樣式包。

MatrialApp裡的title屬性: App的名稱

Scaffold組件出現在MaterialApp組件中的home區域, 他代表一個腳手架。

appBar屬性: 標題欄, 用到了AppBar組件, 組件中包含一個title屬性。

body: 標題欄下方的身體區域, 後面的Center組件代表四方位居中組件,再在裡面寫代碼接著填充東西。



文本組件Text

在flutter當中, 一切都是組件, TextWidget就是基本組件效果之一。

爲了學習TextWidget, 我們在child: Text掛件裡面接著填充更多的内容, 以展示Text内部調用style等衆多方法的效果。

以下是案例:

import 'package:flutter/material.dart';

void main()=>runApp(MyApp());

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'TextWidget展示效果',
      home: Scaffold(
        appBar: AppBar(
          title: Text('我是文本掛件的標題'),
        ),
        body: Center(
          child: Text(
              '我是文本掛件的内容,内容包含一大堆如此這般,内容包含一大堆如此這般,内容包含一大堆如此這般,内容包含一大堆如此這般,内容包含一大堆如此這般,内容包含一大堆如此這般',
            textAlign: TextAlign.left,
            maxLines: 2,
            overflow: TextOverflow.fade,
            style: TextStyle(
              fontSize: 25.0,
              color: Color.fromARGB(255, 255, 150, 150),
              decoration: TextDecoration.underline,
              decorationStyle: TextDecorationStyle.solid,
            ),
          ),
        ),
      ),
    );
  }
}


上述代碼涉及到了文本對齊, 最大行數, 溢出處理和細節樣式控制這幾個組件方法。

其中:

fontSize屬性表示文字大小,

maxtLines屬性代表最大行數,

overflow屬性代表文字溢出處理方式, 用到TextOverflow對象,

fontSize屬性對應的值是float小數點精確1位, 否則填寫其他將導致報錯。

color屬性當中, Color對象裡的fromARGB, A代表透明度。

docoration屬性是文字修飾類型, 一般都是下劃線, 用到了TextDecoration對象

decorationStyle屬性是修飾的樣式, 這裡用實線, 用到了TextDecorationStyle對象裡的solid


層組件Container

相當於html標簽p中的div標簽,

代碼案例:

import 'package:flutter/material.dart';

void main()=>runApp(MyApp());

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'TextWidget展示效果',
      home: Scaffold(
        appBar: AppBar(
          title: Text('我是文本掛件的標題'),
        ),
        body: Center(
          child: Container(
            child: Text(
              '我是文本掛件的内容,内容包含一大堆如此這般,内容包含一大堆如此這般,内容包含一大堆如此這般,内容包含一大堆如此這般,内容包含一大堆如此這般,内容包含一大堆如此這般',
              textAlign: TextAlign.left,
              maxLines: 2,
              overflow: TextOverflow.fade,
              style: TextStyle(
                fontSize: 25.0,
                color: Color.fromARGB(255, 255, 150, 150),
                decoration: TextDecoration.underline,
                decorationStyle: TextDecorationStyle.solid,
              ),
            ),
            alignment: Alignment.center,
            width:400.0,
            height:300.0,
            color: Colors.lightBlue,
            padding: const EdgeInsets.fromLTRB(10.0,60.0,40.0,0.0),
            margin: const EdgeInsets.all(20.0),
          ),
        ),
      ),
    );
  }
}

上述代碼中, 出現了alignment, width, height, color這幾個屬性, 其中alignment用到了Alignment組件

padding屬性和css一樣, 是child子模塊和文本組件之間存在的内邊距,

margin屬性是child子模塊和body組件之間存在的外邊距


decoration屬性(定義如何修飾)

這個decoration和css當中的text-decoration不一樣, 是修飾這裡的Container盒子模型的, 因爲書寫起來比css複雜, 所以單獨拉出來記錄一下。

用到decoration的語句就不要用color屬性來定義盒子顔色了, 把color屬性注釋掉。

代碼案例如下:

import 'package:flutter/material.dart';

void main()=>runApp(MyApp());

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'TextWidget展示效果',
      home: Scaffold(
        appBar: AppBar(
          title: Text('我是文本掛件的標題'),
        ),
        body: Center(
          child: Container(
            child: Text(
              '我是文本掛件的内容,内容包含一大堆如此這般,内容包含一大堆如此這般,内容包含一大堆如此這般,内容包含一大堆如此這般,内容包含一大堆如此這般,内容包含一大堆如此這般',
              textAlign: TextAlign.left,
              maxLines: 2,
              overflow: TextOverflow.fade,
              style: TextStyle(
                fontSize: 25.0,
                color: Color.fromARGB(255, 255, 150, 150),
                decoration: TextDecoration.underline,
                decorationStyle: TextDecorationStyle.solid,
              ),
            ),
            alignment: Alignment.topLeft,
            width:400.0,
            height:300.0,
//            color: Colors.lightBlue,
            padding: const EdgeInsets.fromLTRB(20.0,60.0,40.0,0.0),
            margin: const EdgeInsets.all(20.0),
            decoration: BoxDecoration(
              gradient: const LinearGradient(
                  colors: [
                    Colors.red,
                    Colors.greenAccent,
                    Colors.tealAccent
                  ]
              )
            ),
          ),
        ),
      ),
    );
  }
}

上述代碼當中:

gradient屬性, 定義漸變的意思

LinearGradient組件, 是線性漸變組件的意思。

colors屬性後面多了個s複數, 裡面傳入數組, 再用Colors組件挨個代入元素


圖片組件 Image

Image組件可以通過以下方式來加載:

Image.asset 本地加載, 會導致安裝包過大,

Image.network 常用的通過網路讀圖,

Image.file 本地圖庫加載, 加載圖庫地址xxx, 用戶拍完照, 把圖片讀進來,

Image.memory 透過内存加載, 不常用


以下是代碼案例:

import 'package:flutter/material.dart';

void main()=>runApp(MyApp());

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'TextWidget展示效果',
      home: Scaffold(
        appBar: AppBar(
          title: Text('我是文本掛件的標題'),
        ),
        body: Center(
          child: Container(
            child: Image.network(
              'http://www.wkwkk.com/filepool/cover/cover/1804/180415200453_6863.jpg',
              scale: 2.5,
              color: Colors.greenAccent,
              colorBlendMode: BlendMode.colorBurn,
              fit: BoxFit.cover,
//              repeat: ImageRepeat.repeatY,
            ),
            color: Colors.lightBlue,
            width: 400.0,
            height: 300.0,
          ),
          ),
        ),
    );
  }
}

上述代碼當中, 在圖片組件裡涉及到了以下屬性:

scale屬性, 伸縮比例, 這裡要注意, 相對於傳統的css寫法, scale屬性指定的值越大, 圖片反而會越小。

repeat屬性, 和css一樣, 圖片重複方式, 如果寫到Container組件裡, 是要報錯的, 它是圖片組件裡的屬性

fit屬性, 填充方式, 此時scale屬性指定的值失效, 使用BoxFit組件, 也就是盒子模型内填充組件的意思, 一般用到的是BoxFit.cover, 這樣通過不改變寬高比例的方式把圖片剛好覆蓋到圖片上層的Container容器裡, 如果是BoxFit.contain, 則剛剛接觸到最大寬或者最大高的邊界, 圖片就不會膨脹下去。

colorBlendMode屬性, 這個blend順便查了一下字典, 有交融混合調配的意思, 那設定這個屬性的大概目的也就明白了, 指定了color屬性之後, colorBlendMode屬性的值用到了BlendModel組件, 也就是混合模式, 目前1.0版本有那麽十多種可供選擇,這裡也說不清楚,自己上IDE上調整來看吧。


ListView和ListTile組件

這兩個組件通常成對出現, ListView組件相當於html5概念中的ul標簽, ListTile組件相當於html5概念中的li標簽。查字典時看到單詞tile翻譯成甎、瓦片,此時代碼工作者就是搬這個甎的。

代碼案例如下:

import 'package:flutter/material.dart';

void main()=>runApp(MyApp());

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'flutter app test',
      home: Scaffold(
        appBar: AppBar(
          title: Text('ListView'),
        ),
        body: ListView(
          children: <Widget>[
            ListTile(
              leading: Icon(Icons.person),
              title: Text('人物1'),
            ),
            ListTile(
              leading: Icon(Icons.person),
              title: Text('人物2'),
            ),
            ListTile(
              leading: Icon(Icons.person),
              title: Text('人物3'),
            ),
          ],
        ),
        ),
    );
  }
}

上述代碼中,涉及到了children: <Widget>[...]這種dart專用寫法,習慣就好, 之後就在數組裡依次寫進各組件。


ListView組件内, 嵌套Image組件列表

就和html5書寫一樣, 我們想在ul裡面寫上一排圖片, <li><img ... /></li>...<li><img ... /></li>如何做到的呢?

修改上邊一部分代碼片段, 改爲如下:

body: ListView(
  children: <Widget>[
    Image.network('http://www.wkwkk.com/filepool/cover/img_17021914350735944.jpg'),
    Image.network('http://www.wkwkk.com/filepool/cover/img_17021914350735944.jpg'),
    Image.network('http://www.wkwkk.com/filepool/cover/img_17021914350735944.jpg'),
    Image.network('http://www.wkwkk.com/filepool/cover/img_17021914350735944.jpg'),
  ],
),

上述代碼會實現竪向的圖片列表, 有人會糾結於new不new這個Image組件, 無論如何寫法,效果都雷同。


橫向組件列表

ListView組件當中, 有scrollingDirection屬性, 是定義滾動方向的, 其中:

Axis組件就是網格控制組件。

Axis.horizontal 代表橫向滾動

Axis.vertical 代表縱向滾動

代碼案例如下:

import 'package:flutter/material.dart';

void main()=>runApp(MyApp());

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'flutter app test',
      home: Scaffold(
        appBar: AppBar(
          title: Text('ListView橫向列表'),
        ),
        body: Center(
          child: Container(
            height: 200.0,
            child: ListView(
              scrollDirection: Axis.horizontal,
              children: <Widget>[
                Container(
                  width: 180.0,
                  color: Colors.green
                ),
                Container(
                    width: 180.0,
                    color: Colors.lightBlue,
                ),
                Container(
                    width: 180.0,
                    color: Colors.yellowAccent
                ),
                Container(
                    width: 180.0,
                    color: Colors.blueGrey
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

上述代碼中, 使用幾個Container加載色塊, 加以橫向排列來生成了預期效果。


ListView.builder動態列表建立和傳參

以下是代碼案例:

import 'package:flutter/material.dart';

void main()=>runApp(MyApp(
  item: new List<String>.generate(200, (i)=>"Item $i")
));

class MyApp extends StatelessWidget
{
  final List<String> item;

  MyApp({Key key, @required this.item}):super(key:key);

  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: 'flutter app test',
      home: Scaffold(
        appBar: AppBar(
          title: Text('ListView動態列表'),
        ),
        body: ListView.builder(
          itemCount: item.length,
          itemBuilder:(context, index){
            return new ListTile(
              title: new Text("{$item[index]}"),
            );
          }
        ),
      ),
    );
  }
}

上述代碼當中ListView.builer方法即是生成動態列表方法。

在該方法内,

itemCount屬性傳入參數的長度, 即參數名.length

itemBuilder屬性固定寫入兩個參數, context代表上下文, index代表List數組索引, 此時, 值作用域return所返回的是ListTile甎塊, 簡單寫了一個$item套索引的方式來列印出每個List索引指向的值。


GridView組件

以下是代碼案例:

import "package:flutter/material.dart";

void main()=>runApp(MyApp());

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: '電影海報測試',
      home: Scaffold(
        appBar: AppBar(
          title: Text("我是標題"),
        ),
        body: GridView.count(
          padding:const EdgeInsets.all(10.0),
          crossAxisSpacing: 10.0,
          crossAxisCount: 3,
          children: <Widget>[
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
            Text('It was mine'),
          ]
        )
      ),
    );
  }
}

上述代碼當中GridView.count是其中一種寫法,也可以直接寫爲GridView(...)這種方式。

crossAxisSpacing屬性代表橫向格子之間的間距, 可以理解成html的td左右間距,

crossAxisCount屬性代表一行多少個元素,

另外還有一個mainAxisSpacing屬性, 代表竪向(列所在)各個格子之間的間距, 可以理解成html的td上下間距。

這些都可以通過padding屬性來定義格子的間距, 不過padding屬性不允許直接傳double類型值, 需要傳類似EdgeInsets組件中的all方法, 如例子中那樣。


接下來把用Text組件填充的部分做成圖片:

import "package:flutter/material.dart";

void main()=>runApp(MyApp());

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: '電影海報測試',
      home: Scaffold(
        appBar: AppBar(
          title: Text("我是標題"),
        ),
        body: GridView.count(
          // padding:const EdgeInsets.all(10.0),
          crossAxisSpacing: 10.0,
          crossAxisCount: 3,
          mainAxisSpacing: 10.0,
          childAspectRatio: 1.2,
          children: <Widget>[
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
          ]
        )
      ),
    );
  }
}

上述代碼中

childAspectRatio屬性代表的是寬高比,1是正方形,值越大,越寬,反之圖片範圍越高。


GridView組件直接傳值的寫法(不使用count)

代碼案例如下:

import "package:flutter/material.dart";

void main()=>runApp(MyApp());

class MyApp extends StatelessWidget
{
  @override
  Widget build(BuildContext context)
  {
    return MaterialApp(
      title: '電影海報測試',
      home: Scaffold(
        appBar: AppBar(
          title: Text("我是標題"),
        ),
        body: GridView(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          // padding:const EdgeInsets.all(10.0),
          crossAxisSpacing: 10.0,
          crossAxisCount: 3,
          mainAxisSpacing: 10.0,
          childAspectRatio: 1.2,
          ),
          children: <Widget>[
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
            Image.network(
              'http://www.wkwkk.com/filepool/cover/img_17020900372744314.jpg',
              fit: BoxFit.cover,
            ),
          ]
        )
      ),
    );
  }
}


閲完此文,您的感想如何?
  • 有用

    0

  • 沒用

    0

  • 開心

    0

  • 憤怒

    0

  • 可憐

    0

1.如文章侵犯了您的版權,請發郵件通知本站,該文章將在24小時内刪除;
2.本站標注原創的文章,轉發時煩請注明來源;
3.交流群: 2702237 13835667

相關課文
  • Invalid prop custom validator check failed for prop navigationBarTextStyle

  • svg是什麽文档格式?如何打開svg文档?

  • Cordova報錯Could not find an installed version of Gradle either in Android Studio

  • 支付寶小程序不支持html語法富文本,在Uniapp上的解決方法

我要說說
網上賓友點評