Flutter入門(mén)二: 熟悉Widget、文字樣式、ListView

Flutter入門(mén) 學(xué)習(xí)大綱

上一節(jié),我們完成了Flutter的環(huán)境搭建。本節(jié),我們開(kāi)始搭建項(xiàng)目,簡(jiǎn)單了解Flutter及其基礎(chǔ)組件

  1. 項(xiàng)目創(chuàng)建
    1.1 命令行創(chuàng)建
    1.2 Android Studio創(chuàng)建
  2. 熟悉工程
    2.1 簡(jiǎn)單實(shí)現(xiàn)
    2.2 熟悉widget
    2.3 Text
    2.4 MaterialApp
    2.5 ListView 列表視圖
  3. 常用基礎(chǔ)組件
    3.1 基礎(chǔ)文本
    3.2 富文本
    3.3 基礎(chǔ)容器Container

1. 項(xiàng)目創(chuàng)建

1.1 命令行創(chuàng)建

以前不支持 駝峰寫(xiě)法,需要通過(guò)小寫(xiě)字母+下劃線_命名,但是現(xiàn)在支持

flutter create flutter_demo
  • 創(chuàng)建成功
image.png
  • 按照指令,到指定文件夾運(yùn)行項(xiàng)目
cd FlutterDemo
flutter run

注意:

  • 如果此時(shí)未打開(kāi)模擬器,會(huì)提示需要選擇一個(gè)模擬器。
  • 如果此時(shí)打開(kāi)了多個(gè)模擬器,也會(huì)提示您選中一個(gè)模擬器來(lái)運(yùn)行。
    image.png
  • 選中模擬器后,flutter會(huì)自動(dòng)使用Xcode工具進(jìn)行編譯。
    image.png
  • 如果需要真機(jī)調(diào)試,我們需要手動(dòng)打開(kāi)項(xiàng)目工程,去Xcode配置證書(shū)

終端運(yùn)行Flutter命令鍵

Flutter run key commands.
r Hot reload. ?????? 熱重載(比對(duì)被修改部分,更新被修改代碼)
R Hot restart.      熱重啟(所有資源重新加載)
h Repeat this help message.
d Detach (terminate "flutter run" but leave application running).
c Clear the screen
q Quit (terminate the application on the device).
s Save a screenshot to flutter.png.
b Toggle the platform brightness setting (dark and light mode).                   (debugBrightnessOverride)
w Dump widget hierarchy to the console.                                                      (debugDumpApp)
t Dump rendering tree to the console.                                                 (debugDumpRenderTree)
L Dump layer tree to the console.                                                      (debugDumpLayerTree)
S Dump accessibility tree in traversal order.                                          (debugDumpSemantics)
U Dump accessibility tree in inverse hit test order.                                   (debugDumpSemantics)
i Toggle widget inspector.                                         (WidgetsApp.showWidgetInspectorOverride)
I Toggle oversized image inversion ???.                                        (debugInvertOversizedImages)
p Toggle the display of construction lines.                                         (debugPaintSizeEnabled)
o Simulate different operating systems.                                             (defaultTargetPlatform)
z Toggle elevation checker.
g Run source code generators.
M Write SkSL shaders to a unique file in the project directory.
v Launch DevTools.
P Toggle performance overlay.                                           (WidgetsApp.showPerformanceOverlay)
a Toggle timeline events for all widget build methods.
  • 如果使用安卓模擬器,可以在頂部控制欄配置模擬器
    image.png
  • 選中模擬器,運(yùn)行:


    image.png
  • 由于個(gè)人習(xí)慣,我更喜歡Xcode開(kāi)發(fā),在終端使用命令運(yùn)行。執(zhí)行flutter run時(shí),會(huì)讓我們選擇想使用的模擬器(后續(xù)我主要使用iPhone模擬器)。

1.2 Android Studio創(chuàng)建

  • 除了使用flutter create命令創(chuàng)建項(xiàng)目,我們還可使用Android Studio創(chuàng)建,也可以使用VSCode創(chuàng)建,它們都有flutter插件。
  • 啥? 你問(wèn)Xcode是否可以創(chuàng)建?
    想想蘋(píng)果谷歌的競(jìng)爭(zhēng)者關(guān)系,就知道蘋(píng)果不可能做這樣的支持插件的。??

1.2.1 使用Android Studio創(chuàng)建

image.png
  • 四種創(chuàng)建方式:
image.png
  • 項(xiàng)目基本信息

    image.png

  • 項(xiàng)目唯一標(biāo)識(shí)支持平臺(tái)

    image.png

  • 點(diǎn)Finish后,會(huì)進(jìn)行網(wǎng)絡(luò)請(qǐng)求,拉取資源,創(chuàng)建成功。
    (如果沒(méi)配置鏡像,拉取資源非常緩慢。 上一節(jié)有介紹如何配置鏡像

    image.png

  • 坑點(diǎn)
    如果Android Studio 正在運(yùn)行項(xiàng)目,我們command + Q強(qiáng)制退出。下次打開(kāi)Android Studio時(shí),會(huì)回到當(dāng)時(shí)的緩存。如果緩存成功找回,會(huì)運(yùn)行正常。如果緩存找不到,會(huì)導(dǎo)致無(wú)法運(yùn)行,而且新建工程無(wú)法運(yùn)行。

  • 處理方式:
    刪除flutter目錄下cache緩存文件夾中的lockfile文件,再運(yùn)行項(xiàng)目即可。(相當(dāng)于XCodeClean操作)

# pwd請(qǐng)?zhí)鎿Q為自己flutter的文件目錄
rm /pwd/flutter/bin/cache/lockfile

2. 熟悉工程

  • 創(chuàng)建項(xiàng)目后,可以看到main.dart很多代碼。我們最快熟悉的方式是: 全部刪除,手動(dòng)實(shí)現(xiàn)分析
    image.png

2.1 簡(jiǎn)單實(shí)現(xiàn)

Flutter中,我們使用的開(kāi)發(fā)語(yǔ)言Dart,現(xiàn)在我們先體驗(yàn),完整的Dart語(yǔ)法,我們可以去官網(wǎng)了解

  • 手動(dòng)實(shí)現(xiàn):
// 以下代碼,均使用Dart語(yǔ)言編寫(xiě)

// 資源包  (可以理解為我們iOS的UIKit)
import 'package:flutter/material.dart';

// main入口函數(shù)  (就像iOS main.m中的main函數(shù))
void main() {
  // runApp(app); // runApp就像iOS的 UIApplication, 而app就像我們的根控制器
  // flutter中沒(méi)有控制器和視圖的概念,都是widget組件。
  runApp(
    Center(  //我們用Center部件,自動(dòng)居中展示。這是Center的構(gòu)造函數(shù)
      // child就像subView
      // Text是一種文本框樣式,設(shè)置默認(rèn)值和顯示方向(ltf: left to right 從左到右)
      child: Text('Hello', textDirection: TextDirection.ltr,),
    )
  );
}
  • flutter運(yùn)行,文本框成功展示
    image.png

2.2 熟悉widget

Widget: 作用類似于OC中的UIView,是小部件。分為兩大類:

  • StatelessWidget:無(wú)狀態(tài)組件??旖萱Istless。
    創(chuàng)建后決定了樣式,狀態(tài)更改需要手動(dòng)創(chuàng)建新widget。

  • StatefulWidget: 有狀態(tài)組件。快捷鍵stful。
    本質(zhì)上也是無(wú)狀態(tài)組件,渲染時(shí)無(wú)狀態(tài),因?yàn)?code>UI本身是無(wú)狀態(tài)的。但它會(huì)保留組件狀態(tài),記錄組件狀態(tài)的屬性改變時(shí),會(huì)自動(dòng)重新渲染。直到該組件完全銷毀,才會(huì)釋放記錄的屬性

2.2.1 無(wú)狀態(tài)組件(StatelessWidget)
  • 我們將main入口的Center組件改成自定義MyWidget無(wú)狀態(tài)組件。
import 'package:flutter/material.dart';

void main() {
  runApp(
    MyWidget(), //()是構(gòu)造函數(shù),類似C++。
  );
}

// 無(wú)狀態(tài)Widget快捷鍵是 stless
// 一個(gè)Widget,就是一個(gè)class類
class MyWidget extends StatelessWidget {
  @override
  // build:會(huì)將小部件放到渲染樹(shù)中去
  // 渲染樹(shù): 會(huì)從main入口的第一個(gè)widget開(kāi)始渲染,然后以樹(shù)結(jié)構(gòu)依次向下渲染組件
  // 所有widget都必須有build方法,build返回的是什么,MyWidget在外界渲染的就是什么
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        'Hello Flutter2',
        textDirection: TextDirection.ltr,
      ),
    );
  }
}
  • 選擇模擬器debug運(yùn)行,模擬器啟動(dòng)后,可以修改文本內(nèi)容,點(diǎn)擊熱重載按鈕,感受熱重載的強(qiáng)大。
image.png
  • reload熱重載功能,是通過(guò)比較新舊代碼變化,來(lái)更新被改動(dòng)部分代碼的。 但是有些場(chǎng)景熱重載失敗的,只能restart重啟才可以。

具體場(chǎng)景,參考Flutter官網(wǎng)介紹

Dart語(yǔ)言簡(jiǎn)寫(xiě):

  • Dart語(yǔ)言中,如果函數(shù)只有一行內(nèi)容時(shí),可以使用=>縮寫(xiě):
// 改動(dòng)前
//void main() {
//  runApp(MyWidget());
//}
// 簡(jiǎn)寫(xiě):
void main() => runApp(MyWidget()); 

2.3 Text

  • Text是一個(gè)文本組件,是StatelessWidget不可變組件。
2.3.1 構(gòu)造函數(shù)與參數(shù)
  • Text為例,構(gòu)造函數(shù)是Text(),包含必選參數(shù)可選值,可選值可以賦默認(rèn)值
    image.png
2.3.2 final和const修飾符

finalconst都類似于Swiftlet,是不可變的。

  • final可以不賦初始值,運(yùn)行時(shí)賦值。
  • const必須在創(chuàng)建時(shí)就賦值。

比如Text使用頻率最高styletextAlign,都是final聲明,因?yàn)?code>Text本身是StatelessWidget不可變的組件。

image.png

  • Text加入樣式,使用變量創(chuàng)建TextStyle,_下劃線表示私有變量
import 'package:flutter/material.dart';

// 入口,展示MyWidget組件
void main() => runApp(MyWidget());

class MyWidget extends StatelessWidget {
  @override
  // build 確定組件返回的內(nèi)容
  Widget build(BuildContext context) {

    // final創(chuàng)建一個(gè)_textStyle不可變變量,_開(kāi)頭的屬性,表示私有屬性
    final _textStyle = TextStyle(color: Colors.red, fontSize: 40.0, fontWeight: FontWeight.bold);

    return Center(
      child: Text(
        'Hello Flutter',
        textDirection: TextDirection.ltr,
        style: _textStyle, // 直接使用變量
      ),
    );
  }
}

TextTextStyle相關(guān)屬性參數(shù),可以Command + 鼠標(biāo)左鍵查看

image.png

2.4 MaterialApp

  • MaterialApp:Flutter推薦方式,提供快速構(gòu)建APP的方式(包括導(dǎo)航欄、內(nèi)容、主題等)
  • home: 類似于根控制器,需要指定一個(gè)widget
    Scaffold: 類似于導(dǎo)航控制器NavigationController,包含導(dǎo)航欄相關(guān)屬性。是一個(gè)可變組件statefulWidget
    appBar:導(dǎo)航欄
    body: 內(nèi)容
  • theme主題,可控制主題色
import 'package:flutter/material.dart';

// 入口,展示MyWidget組件
void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // MaterialApp:Flutter推薦方式,提供快速構(gòu)建APP的方式(包括導(dǎo)航欄、內(nèi)容、主題等)
    return MaterialApp(
      // home: 類似于根控制器,也是需要指定一個(gè)widget
      // Scaffold: 類似于導(dǎo)航控制器NavigationController,包含導(dǎo)航欄相關(guān)屬性。是一個(gè)可變組件statefulWidget
      home: Scaffold(
        // appBar:導(dǎo)航欄
        appBar: AppBar(
              title: Text('Flutter Demo'),
            ),
        // body: 內(nèi)容
        body: MyWidget(),
      ),
      // theme:主題,可控制主題色
      theme: ThemeData(
        primaryColor: Colors.yellow
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  @override
  // build 確定組件返回的內(nèi)容
  Widget build(BuildContext context) {

    // final創(chuàng)建一個(gè)_textStyle不可變變量,_開(kāi)頭的屬性,表示私有屬性
    final _textStyle = TextStyle(color: Colors.red, fontSize: 40.0, fontWeight: FontWeight.bold);

    return Center(
      child: Text(
        'Hello Flutter',
        textDirection: TextDirection.ltr,
        style: _textStyle, // 直接使用變量
      ),
    );
  }
}
image.png

2.5 ListView 列表視圖

  • 列表視圖:類似iOS的UITableView,但是沒(méi)有Section的概念。
2.5.1 準(zhǔn)備Model

在布局之前,先準(zhǔn)備數(shù)據(jù)

  • 新建Model文件夾,新建car.dart文件:
    image.png
// 不需要導(dǎo)入material.dart,因?yàn)镃ar直接繼承Object

// Car 模型
class Car {
  // 構(gòu)造函數(shù): {}內(nèi)是可選值
  const Car({
    this.name,
    this.imageUrl,
  });

  // 名稱
  final String name;
  // 圖片鏈接
  final String imageUrl;
}

final List<Car> datas = [
  Car(
    name: '保時(shí)捷918 Spyder',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-7d8be6ebc4c7c95b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '蘭博基尼Aventador',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-e3bfd824f30afaac?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '法拉利Enzo',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-a1d64cf5da2d9d99?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: 'Zenvo ST1',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-bf883b46690f93ce?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '邁凱倫F1',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-5a7b5550a19b8342?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  ),
  Car(
    name: '薩林S7',
    imageUrl:
    'https://upload-images.jianshu.io/upload_images/2990730-2e128d18144ad5b8?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
  )
];
2.5.2 設(shè)置ListView
  • 如果直接導(dǎo)入Car模型,需要導(dǎo)入頭文件

三種導(dǎo)入頭文件的方式

  1. 直接手寫(xiě),在頂部import
  2. 左鍵點(diǎn)擊Car,出現(xiàn)紅色小燈泡,點(diǎn)擊import Library
  3. 鼠標(biāo)光標(biāo)放在Car上,按住Option+Enter鍵,再按一次Enter鍵,可快捷導(dǎo)入import Library

final List<Car> datas = []

  • Container: 類似于htmldiv,也類似于iOSUIView,就是用來(lái)放東西的。需要設(shè)置大小(也可以被子控件撐出大?。?/li>
  • Column: 內(nèi)容垂直排列的容器
  • row: 內(nèi)容水平排列的容器
  • stack: 內(nèi)容重疊的容器
  • Image圖片可變組件network加載網(wǎng)絡(luò)圖片
  • SizedBox: 空容器,有大小。(有時(shí)為了便于內(nèi)部插入元素,會(huì)直接使用Container
  • MaterialAppdebugShowCheckedModeBanner隱藏導(dǎo)航欄Debug角標(biāo)
import 'package:flutter/material.dart';

import 'Model/car.dart';

// 入口,展示MyWidget組件
void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // MaterialApp:Flutter推薦方式,提供快速構(gòu)建APP的方式(包括導(dǎo)航欄、內(nèi)容、主題等)
    return MaterialApp(
      // 隱藏導(dǎo)航欄Debug角標(biāo)
      debugShowCheckedModeBanner: false,
      // home: 類似于根控制器,需要指定一個(gè)widget
      home: Home(),
      // theme:主題,可控制主題色
      theme: ThemeData(
        primaryColor: Colors.yellow
      ),
    );
  }
}

// Home 組件
class Home extends StatelessWidget {

  // 回調(diào)函數(shù),返回widget組件
  Widget _cellForRow(BuildContext context, int index) {
    // Container類似于html的div,也類似于iOS的UIView,就是用來(lái)放東西的
    // 需要大?。ㄒ部梢员蛔涌丶纬龃笮。?    return Container(
        color: Colors.white,
        // height: 20,
        margin:  EdgeInsets.all(10), //EdgeInsets.only(top: 1),
        // 子控件
        // Column 內(nèi)容垂直排列的容器 row 內(nèi)容水平排列的容器 stack 內(nèi)容重疊的容器
        // Image圖片可變組件,network加載網(wǎng)絡(luò)圖片
        child: Column(
          children: <Widget>[
            Image.network(datas[index].imageUrl),
            SizedBox(height: 8,),
            Text(
              datas[index].name,
              style: TextStyle(
                  fontWeight: FontWeight.bold,
                fontSize: 18.0,
                fontStyle: FontStyle.italic),),
            SizedBox(height: 8,)
          ]
        )
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[100],
      appBar: AppBar(
        title: Text("Flutter Demo"),
      ),
      // ListView 列表組件(沒(méi)有iOS的Section概念)
      body: ListView.builder(
        // cell個(gè)數(shù)
        itemCount: datas.length,
        // cell內(nèi)容(等同與cellForRow)build 是渲染
        // iOS中是使用代理和協(xié)議完成,這里是直接使用回調(diào)函數(shù),有兩個(gè)入?yún)?        itemBuilder: _cellForRow,
      ),
    );
  }
}

// 模型數(shù)組
// 沒(méi)導(dǎo)入頭文件時(shí),會(huì)提示需要導(dǎo)入Car頭文件
// 三種導(dǎo)入頭文件的方式
// 1. 直接手寫(xiě),在頂部import
// 2. 左鍵點(diǎn)擊Car,出現(xiàn)紅色小燈泡,點(diǎn)擊import Library
// 3. 鼠標(biāo)光標(biāo)放在Car上,按住Option+Enter鍵,再按一次Enter鍵,可快捷導(dǎo)入import Library
// final List<Car> datas = []
  • 效果展示:


    image.png
  • 實(shí)際開(kāi)發(fā)中,我們可以將ListView內(nèi)容抽離出來(lái),做成單獨(dú)文件listView_demo.dart:

import 'package:flutter/material.dart';

import 'car.dart';

class ListViewDemo extends StatelessWidget {

  // 回調(diào)函數(shù),返回widget組件
  Widget _cellForRow(BuildContext context, int index) {
    return Container(
        color: Colors.white,
        margin:  EdgeInsets.all(10)
        child: Column(
            children: <Widget>[
              Image.network(datas[index].imageUrl),
              SizedBox(height: 8,),
              Text(
                datas[index].name,
                style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 18.0,
                    fontStyle: FontStyle.italic),),
              SizedBox(height: 8,)
            ]
        )
    );
  }

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      // cell個(gè)數(shù)
      itemCount: datas.length,
      itemBuilder: _cellForRow,
    );
  }
}
  • main.dart中,直接使用我們封裝的ListViewDemo導(dǎo)入頭文件)即可:
import 'package:flutter/material.dart';

import 'Model/listView_demo.dart';

// 入口,展示MyWidget組件
void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // MaterialApp:Flutter推薦方式,提供快速構(gòu)建APP的方式(包括導(dǎo)航欄、內(nèi)容、主題等)
    return MaterialApp(
      // 隱藏導(dǎo)航欄Debug角標(biāo)
      debugShowCheckedModeBanner: false,
      // 根組件
      home: Home(),
      // 主題
      theme: ThemeData(
        primaryColor: Colors.yellow
      ),
    );
  }
}

// Home 組件
class Home extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[100],
      appBar: AppBar(
        title: Text("Flutter Demo"),
      ),
      // 列表
      body: ListViewDemo(),
    );
  }
}

3. 常用基礎(chǔ)組件

  • 上面講了簡(jiǎn)單封裝,我們現(xiàn)在對(duì)幾個(gè)基礎(chǔ)組件進(jìn)行簡(jiǎn)單封裝

3.1 基礎(chǔ)文本

  • 新建一個(gè)base_widget.dart文件,創(chuàng)建TextDemo組件:
  1. 通過(guò)屬性聲明變量內(nèi)容樣式),_開(kāi)頭的屬性為私有屬性。
  2. $ + 屬性名快捷插入變量內(nèi)容。 如果后面有其他字符等信息,可使用{}包裹起來(lái)。
  3. Text可設(shè)置maxLines最大行數(shù),超出部分樣式通過(guò)overflow設(shè)置(ellipsis尾部省略號(hào)
import 'package:flutter/material.dart';

//【普通文本 Demo】
class TextDemo extends StatelessWidget {
  // 文本樣式(私有屬性)
  final TextStyle _textStyle = TextStyle(
    fontSize: 24.0,
  );

  final String _title = 'Flutter入門(mén)';
  final String _author = 'HT';

  @override
  Widget build(BuildContext context) {

    // $ + 屬性名: 快捷插入變量?jī)?nèi)容。 如果后面有其他字符等信息,可使用{}包裹起來(lái)。
    return Text(
      '《$_title》這是一個(gè)TextDemo,使用Flutter開(kāi)發(fā)。由iOS開(kāi)發(fā)者${_author}開(kāi)發(fā),快速配置,簡(jiǎn)易上手的零基礎(chǔ)學(xué)習(xí)方式。歡迎閱讀和上手練習(xí),不懂之處,留言交流',
      textAlign: TextAlign.center,
      style: _textStyle,
      maxLines: 4, // 最多4行
      overflow: TextOverflow.ellipsis, // 超出顯示省略號(hào)
    );
  }
}
  • main.dart中指定bodyTextDemo:
    image.png
  • 展示樣式:


    image.png

3.2 富文本

  • 使用RichText組件,通過(guò)給text指定TextSpan類型,添加children:<TextSpan>數(shù)組,數(shù)組內(nèi)創(chuàng)建TextSpan,并賦值樣式即可:
import 'package:flutter/material.dart';

//【富文本 Demo】
class RichTextDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RichText(
      //基礎(chǔ)元素
      text: TextSpan(
          text: '《Flutter 入門(mén)》',
          style: TextStyle(
            fontSize: 30,
            color: Colors.black,
          ) ,
          // 子元素
          children:<TextSpan>[
            // 元素一
            TextSpan(
              text: 'HT',
              style: TextStyle(
                fontSize: 20,
                color: Colors.blue,
              ),
            ),
            // 元素二
            TextSpan(
              text: '666',
              style: TextStyle(
                fontSize: 40,
                color: Colors.red,
              ),
            ),
          ]),
    );
  }
}
  • main.dart中指定bodyRichTextDemo:
    image.png
  • 展示樣式:


    image.png

3.3 基礎(chǔ)容器Container

  • 創(chuàng)建基礎(chǔ)組件BaseWidgetDemo,返回Container組件:
//【基礎(chǔ)組件Demo】
class BaseWidgetDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 容器背景藍(lán)色(沒(méi)有給定大小時(shí),根據(jù)子視圖大小撐開(kāi))
    return Container(
      color: Colors.blue,
      // 子視圖橫向布局
      child: Row(
        children: <Widget>[
          Container(
            // 內(nèi)邊距
            padding: EdgeInsets.only(left: 10,top: 10,right: 10,bottom: 10),
            // 外邊距
            margin: EdgeInsets.only(left: 10,top: 10,right: 10,bottom: 10),
            // 子元素紅色
            color: Colors.red,
            // 子元素內(nèi)容包含?號(hào)圖片
            child: Icon(Icons.add),
          ),
          Container(
            // 子元素紅色
            color: Colors.red,
            // 子元素內(nèi)容包含?號(hào)圖片
            child: Icon(Icons.add),
          ),
        ],
      ),
    );
  }
}
image.png
  • 展示樣式:


    image.png
  • Dart中沒(méi)有iOSButton概念:
    因?yàn)?code>Button實(shí)際是圖片 + 文字 + 手勢(shì) + 狀態(tài)組成,以及封裝相應(yīng)的響應(yīng)事件。我們一般使用手勢(shì)小部件,包裝圖片文字即可。

【快捷鍵】
command + option + L:自動(dòng)格式化
command + -:折疊當(dāng)前函數(shù)
command + shift + -:折疊全部函數(shù)
command + {:回到上一步
command + }: 回到下一步
command + shift + O: 快速到指定文件
stless:不可變組件
stful: 可變組件


本節(jié)主要是Flutter基礎(chǔ)體驗(yàn),通過(guò)本節(jié),其實(shí)我們已經(jīng)感受到了Flutter便捷。
下一節(jié),Flutter入門(mén)三:自動(dòng)布局(Row/Column/Stack)與兩種Widget

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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