Flutter之基礎Widget

Flutter

  • 原文博客地址: Flutter之基礎Widget
  • Flutter和Dart系列文章
  • 項目GitHub地址
  • Flutter做爲一種全新的響應式,跨平臺,高性能, 徹底免費、開源的移動開發框架
  • WidgetFlutter開發中的主要組成部分, 是Flutter的基礎, Flutter的核心設計思想即是: 一切皆Widget
  • Flutter中的widget的概念更普遍,它不只能夠表示UI元素,也能夠表示一些功能性的組件如:用於手勢檢測的 GestureDetector widget、用於應用主題數據傳遞的Theme等等

Flutter框架

Widget與Element

  • Widget實際上就是Element的配置數據, Widget的功能是描述一個UI元素的一個配置數據, 而真正的UI渲染是由Element構成
  • 因爲Element是經過Widget生成,因此它們之間有對應關係,因此在大多數場景,咱們能夠寬泛地認爲Widget就是指UI控件或UI渲染
  • 一個Widget對象能夠對應多個Element對象。這很好理解,根據同一份配置(Widget),能夠建立多個實例(Element

Widget類的聲明

@immutable
abstract class Widget extends DiagnosticableTree {
  /// Initializes [key] for subclasses.
  const Widget({ this.key });

  /// See also the discussions at [Key] and [GlobalKey].
  final Key key;

  /// multiple times.
  @protected
  Element createElement();

  /// A short, textual description of this widget.
  @override
  String toStringShort() {
    return key == null ? '$runtimeType' : '$runtimeType-$key';
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
  }

  static bool canUpdate(Widget oldWidget, Widget newWidget) {
    return oldWidget.runtimeType == newWidget.runtimeType
        && oldWidget.key == newWidget.key;
  }
}
複製代碼
  • Widget類繼承自DiagnosticableTree,主要做用是提供調試信息。
  • Key: 這個key屬性相似於React/Vue中的key,主要的做用是決定是否在下一次build時複用舊的widget,決定的條件在canUpdate()方法中
  • createElement():正如前文所述一個Widget能夠對應多個ElementFlutter Framework在構建UI時,會先調用此方法生成對應節點的Element對象。此方法是Flutter Framework隱式調用的,在咱們開發過程當中基本不會調用到。
  • debugFillProperties 複寫父類的方法,主要是設置DiagnosticableTree的一些特性。
  • canUpdate是一個靜態方法,它主要用於在Widget樹從新build時複用舊的widget
    • 具體來講就是:是否用新的Widget對象去更新舊UI上所對應的Element對象的配置;
    • 經過其源碼咱們能夠看到,只要newWidgetoldWidgetruntimeTypekey同時相等時就會用newWidget去更新Element對象的配置,不然就會建立新的Element

StatelessWidget和StatefulWidget的區別

  • StatelessWidget是狀態不可變的widget, 初始狀態設置之後就不可再變化, 若是須要變化須要從新建立; StatefulWidget能夠保存本身的狀態
  • Flutter中經過引入State來保存狀態, 當State的狀態改變時,能從新構建本節點以及孩子的Widget樹來進行UI變化
  • 若是須要主動改變State的狀態,須要經過setState()方法進行觸發,單純改變數據是不會引起UI改變的
  • 下面介紹部分的Widget組件

Text

UI上面文字的展現基本上都要靠Text組件來完成html

// 兩種構造函數
// 顯示普通的文本
 const Text(this.data, {
    Key key,
    this.style,
    this.textAlign,
    this.textDirection,
    this.locale,
    this.softWrap,
    this.overflow,
    this.textScaleFactor,
    this.maxLines,
    this.semanticsLabel,
  }) : assert(data != null),
       textSpan = null,
       super(key: key);

  /// 段落式文本,能夠給文本中的每一個textSpan設置其樣式
  const Text.rich(this.textSpan, {
    Key key,
    this.style,
    this.textAlign,
    this.textDirection,
    this.locale,
    this.softWrap,
    this.overflow,
    this.textScaleFactor,
    this.maxLines,
    this.semanticsLabel,
  }): assert(textSpan != null),
      data = null,
      super(key: key);

複製代碼

參數介紹

data

文本的內容git

Text('titanjun')
複製代碼

style

文本的樣式github

const TextStyle({
    this.inherit = true,
    this.color,
    this.fontSize,
    this.fontWeight,
    this.fontStyle,
    this.letterSpacing,
    this.wordSpacing,
    this.textBaseline,
    this.height,
    this.locale,
    this.foreground,
    this.background,
    this.shadows,
    this.decoration,
    this.decorationColor,
    this.decorationStyle,
    this.debugLabel,
    String fontFamily,
    String package,
  }) : fontFamily = package == null ? fontFamily : 'packages/$package/$fontFamily',
       assert(inherit != null),
       assert(color == null || foreground == null, _kColorForegroundWarning);
       
// 相關屬性介紹
1. inherit: 爲false時不顯示

2. color: 字體顏色

3. fontSize: 字體大小, 默認是14.0

4. fontWeight: 字體的粗體

5. fontStyle: 字體的樣式
    normal正常 italic 斜體

6. letterSpacing: 字符間距

7. wordSpacing: 單詞間距

8. textBaseline
    alphabetic:用於對齊字母字符底部的水平線
    ideographic:用於對齊表意字符的水平線
    
9. height: 用在Text控件上的時候,會乘以fontSize作爲行高,

10. locale: 國際化

11. foreground: 用paint來渲染text,也能夠用他來改變字體顏色等

12. background: 背景顏色

13. decoration: 
    下劃線 underline、 刪除線 lineThrough、上劃線 overline,默認是無 none
    
14. decorationStyle: decoration線的樣式
    solid: 直線, double: 兩條線, dotted: 短虛線, dashed: 長虛線, wavy: 波浪線

15. decorationColor: decoration線的顏色

16. debugLabel: 文本樣式的描述, 該屬性只在調試中維護

17. fontFamily和package(自定義字體的時候用的到,後面再詳解)
複製代碼

使用樣式示例web

style: TextStyle(
    inherit: true,
    color: Colors.red,
    fontSize: 50,
    fontWeight: FontWeight.bold,
    fontStyle: FontStyle.italic,
    letterSpacing: 2,
    wordSpacing: 5,
    textBaseline: TextBaseline.alphabetic,
    height: 2,
    locale: Locale('CH'),
    decoration: TextDecoration.lineThrough,
    decorationColor: Colors.blue,
    decorationStyle: TextDecorationStyle.wavy,
),
複製代碼

textAlign

文本顯示方向算法

left: 居左顯示
center: 居中顯示
right: 居右顯示
justify: 文本的拉伸行,其末尾用軟換行符填充寬度
start: 對齊容器前緣的文本。
    對於從左到右的文本([TextDirection.ltr]),這是左邊緣。
    對於從右到左的文本([TextDirection.rtl]),這是右邊緣。
end: 對齊容器尾部邊緣的文本。
    對於從左到右的文本([TextDirection.ltr]),這是右邊緣。
    對於從右到左的文本([TextDirection.rtl]),這是左邊緣。
複製代碼

textDirection

和上述TextAlign.start和TextAlign.end同樣數組

softWrap

文本是否能換行,bool類型緩存

overflow

用來指定超出文本的表示方式,是截斷文本啊仍是用三個點顯示等bash

ellipsis: ...形式顯示
clip: 直接截斷
fade: 效果和clip同樣
複製代碼

maxLines

用來指定文本最多顯示多少行微信

textScaleFactor

文本字體的縮放倍數,如:1.5則在默認字體上變成1.5倍大小字體,0.5則是0.5倍markdown

Text構造函數

child: Text(
      // 須要顯示的文字
      'titanjun.top' * 3,
      textAlign: TextAlign.left,
      textDirection: TextDirection.ltr,
      locale: Locale('CH'),
      maxLines: 1,
      overflow: TextOverflow.fade,
      style: TextStyle(
          inherit: true,
          color: Colors.red,
          fontSize: 50,
          fontWeight: FontWeight.bold,
          fontStyle: FontStyle.italic,
          letterSpacing: 2,
          wordSpacing: 5,
          textBaseline: TextBaseline.alphabetic,
          height: 2,
          locale: Locale('CH'),
          decoration: TextDecoration.lineThrough,
          decorationColor: Colors.blue,
          decorationStyle: TextDecorationStyle.wavy,
      ),
  ),
複製代碼

Text.rich構造函數

這個構造函數和iOS中用到的富文本相似

child: Text.rich(
    TextSpan(
      text: '博客地址: ',
      children: [
        TextSpan(
          text: 'https://',
          style: TextStyle(color: Colors.red)
        ),
        TextSpan(
          text: 'titanjun.top',
          style: TextStyle(color: Colors.blue),
        ),
        TextSpan(
          text: '歡迎訪問',
          style: TextStyle(color: Colors.orange)
        ),
      ]
    ),
),
複製代碼

Text.rich

其中TextSpan的構造函數以下

const TextSpan({
    this.style,
    this.text,
    // 接受List<TextSpan>類型的數組
    this.children,
    // 文本的手勢操做, 後面說這個
    this.recognizer,
});
複製代碼

Image

  • 一個用於展現圖片的組件。支持 JPEG、PNG、GIF、Animated GIF、WebP、Animated WebP、BMP 和 WBMP 等格式
  • Image共有五種構造函數

image

Image()

const Image({
    Key key,
    // 一個圖片對象ImageProvider, 可設置NetworkImage(), FileImage(), MemoryImage()三種對象
    @required this.image,
    // 圖片的描述, String
    this.semanticLabel,
    this.excludeFromSemantics = false,
    // 圖片的寬度, double
    this.width,
    // 圖片的高度, double
    this.height,
    // 圖像的顏色, 用於和圖片混合的顏色, 結合colorBlendMode使用
    this.color,
    // 顏色和圖片混合的狀態, BlendMode
    this.colorBlendMode,
    // 圖像在佈局中分配的空間, BoxFit
    this.fit,
    // 圖像邊界內對齊圖像, Alignment
    this.alignment = Alignment.center,
    // 未充分填充容器時,是否重複顯示圖片
    this.repeat = ImageRepeat.noRepeat,
    // 九片圖像的中心切點, Rect
    this.centerSlice,
    // 是否在圖像的方向上繪製圖像 TextDirection
    this.matchTextDirection = false,
    // 當圖像提供者發生變化時,是繼續顯示舊圖像(true)仍是暫時不顯示(false)
    this.gaplessPlayback = false,
    // 設置圖片的過濾質量
    this.filterQuality = FilterQuality.low,
  }) 
複製代碼

部分屬性詳解

fit

圖像在佈局中分配的空間, BoxFit枚舉值

  • fill: 填充滿容器空間, 圖片會被拉伸
  • contain: 以容器的大小等比例縮放圖片
  • cover: 填充整個容器, 圖片會被剪切
  • fitWidth: 以容器的寬度, 等比例縮放圖片
  • fitHeight: 以容器的高度, 等比例的縮放圖片
  • none: 以圖片的實際大小顯示
  • scaleDown: 居中顯示, 圖片不會拉伸, 以寬高中最小的尺寸爲標準
alignment

圖像邊界內對齊圖像, Alignment類, 不是枚舉值

/// 定義方式爲垂直方向-水平方向
  static const Alignment topLeft = Alignment(-1.0, -1.0);
  static const Alignment topCenter = Alignment(0.0, -1.0);
  static const Alignment topRight = Alignment(1.0, -1.0);
  static const Alignment centerLeft = Alignment(-1.0, 0.0);
  static const Alignment center = Alignment(0.0, 0.0);
  static const Alignment centerRight = Alignment(1.0, 0.0);
  static const Alignment bottomLeft = Alignment(-1.0, 1.0);
  static const Alignment bottomCenter = Alignment(0.0, 1.0);
  static const Alignment bottomRight = Alignment(1.0, 1.0);
  
  /// 使用方式
  alignment: Alignment.topLeft,
  // 或者
  alignment: Alignment(0.0, 1.0)
複製代碼
Image(
  image: NetworkImage('https://user-gold-cdn.xitu.io/2019/4/19/16a34ef6cd5c73e1?w=1196&h=698&f=jpeg&s=29359'),
  fit: BoxFit.scaleDown,
  alignment: Alignment.topLeft,
),
複製代碼

Image.network

用於顯示網絡圖片

Image.network(
  'https://titanjun.oss-cn-hangzhou.aliyuncs.com/flutter/catimage.jpg',
  width: 100,
  height: 100,
  fit: BoxFit.scaleDown,
  alignment: Alignment.center,
)
複製代碼

網絡請求Image是最多見的操做, 這裏重點說明兩個點

緩存

  • ImageCacheImageProvider默認使用的圖片緩存。ImageCache使用的是LRU的算法
  • 默承認以存儲1000張圖片。若是以爲緩存太大,能夠經過設置ImageCachemaximumSize屬性來控制緩存圖片的數量。
  • 也能夠經過設置maximumSizeBytes來控制緩存的大小(默認緩存大小10MB)

CDN優化

若是想要使用cdn優化,能夠經過url增長後綴的方式實現。默認實現中沒有這個點,可是考慮到cdn優化的可觀收益,建議你們利用好這個優化

Image.asset

  • Flutter應用程序能夠包含代碼和 assets(有時稱爲資源)
  • asset是打包到程序安裝包中的,可在運行時訪問
  • 常見類型的asset包括靜態數據(例如JSON文件),配置文件,圖標和圖片(JPEG,WebP,GIF,動畫WebP / GIF,PNG,BMP和WBMP)
  • Flutter使用pubspec.yaml文件(位於項目根目錄),來識別應用程序所需的asset

image

須要注意的是

  • 圖片所在的文件夾imagespubspec.yaml須要在同一目錄下, 不然pubspec.yaml文件中, 設置資源路徑的時候要對應修改
  • images圖片文件夾中2.0x和3.0x圖片要分別建立兩個文件夾, 並把2倍和3倍圖分別放在不一樣的文件夾中, 切文件的名字不要在帶@2x和@3x字樣

image

Image.asset(
  'images/home.png',
  width: 100,
  height: 100,
  fit: BoxFit.scaleDown,
  alignment: Alignment.center,
)
複製代碼

Image.file

Image.file(File file, {
    Key key,
    double scale = 1.0,
    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,
  })
複製代碼
  • 主要解析file參數,其餘與Image()構造的參數一致!
  • file: 對文件系統上的文件的引用。
  • File 實例是一個對象,它包含能夠在其上執行操做的路徑

Image.memory

Image.memory(Uint8List bytes, {
    Key key,
    double scale = 1.0,
    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,
  })
複製代碼
  • 加載Uint8List資源圖片
  • 主要解析bytes參數,其餘與Image()構造的參數一致!

Icon

  • Flutter中,Icon是相似於web開發中同樣使用iconfont(字體圖標),它是將圖標作成字體文件,而後經過指定不一樣的字符而顯示不一樣的圖片
  • 在字體文件中,每個字符都對應一個位碼,而每個位碼對應一個顯示字形,不一樣的字體就是指字形不一樣,即字符對應的字形是不一樣的
  • 而在iconfont中,只是將位碼對應的字形作成了圖標,因此不一樣的字符最終就會渲染成不一樣的圖標。
  • Fluttericonfont相較於圖片的優點以下:
    • 體積小:能夠減少安裝包大小。
    • 矢量的:iconfont都是矢量圖標,放大不會影響其清晰度。
    • 能夠應用文本樣式:能夠像文本同樣改變字體圖標的顏色、大小對齊等。
    • 能夠經過TextSpan和文本混用。

使用Material Design字體圖標

Flutter默認包含了一套Material Design的字體圖標,在pubspec.yaml文件中的配置以下

flutter:
 uses-material-design: true
複製代碼

若是設置成false, 則圖片效果以下, 圖片顏色爲本身設置的顏色

image

在Text中使用

下面看一個在Text中使用iconfont的示例

String iconStr = "";
// accessible: &#xE914; or 0xE914 or E914
iconStr += "\uE914";
// error: &#xE000; or 0xE000 or E000
iconStr += " \uE000";
// fingerprint: &#xE90D; or 0xE90D or E90D
iconStr += " \uE90D";


Text(iconStr,
  style: TextStyle(
    fontFamily: "MaterialIcons",
    fontSize: 80.0,
    color: Colors.green
  ),
)
複製代碼

上述代碼的運行效果以下

image

任何一個圖片咱們均可以使用Text文本進行展現, 可是這須要咱們提供每個圖標的字符碼點, 可在material-design-icons中搜索查找, 並且並不能固定指定圖片的大小, 只能設置字體的大小, 這並對開發者不友好

Icon介紹

Flutter封裝了一個Icon來專門顯示字體圖標,上面的例子也能夠用以下方式實現

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    Icon(Icons.accessible, color: Colors.green, size: 80),
    Icon(Icons.error, color: Colors.green, size: 80),
    Icon(Icons.fingerprint, color: Colors.green, size: 80),
  ],
)
複製代碼

Icons類中包含了全部Material Design圖標的IconData靜態變量定義, .....我大概算了一下, Icons中大概一共定義了984中圖標

// icon的構造函數
const Icon(this.icon, {
    Key key,
    // double, 設置圖片的大小, 同事設置寬高
    this.size,
    // Color, 設置圖片的顏色
    this.color,
    // String, 圖標的語義標籤
    this.semanticLabel,
    // TextDirection, 從左/右開始排列
    this.textDirection,
})
複製代碼

按鈕

  • Flutter提供了RaisedButtonFlatButtonOutlineButtonIconButton四種按鈕, 除了IconButton以外都是繼承自MaterialButton
  • 全部Material庫中的按鈕都有以下相同點:
    • 按下時都會有「水波動畫」。
    • 有一個onPressed屬性來設置點擊回調,當按鈕按下時會執行該回調,若是不提供該回調則按鈕會處於禁用狀態,禁用狀態不響應用戶點擊

MaterialButton

MaterialButton是除IconButton按鈕以外的其餘按鈕的父類, 下面介紹一下各屬性的使用

const MaterialButton({
    Key key,
    // 點擊事件
    @required this.onPressed,
    // 高亮狀態變化回調,參數:是否高亮,按下時高亮,擡起不高亮
    this.onHighlightChanged,
    // 字體的主體
    this.textTheme,
    // 按鈕文字顏色
    this.textColor,
    // 禁用狀態下按鈕字體顏色
    this.disabledTextColor,
    // 按鈕背景顏色
    this.color,
    // 禁用狀態下背景顏色
    this.disabledColor,
    // 高亮狀態(按下時的背景顏色)
    this.highlightColor,
    // 按鈕的水波紋的顏色
    this.splashColor,
    // 字體亮度
    this.colorBrightness,
    // 按鈕底部陰影效果的偏移量, double
    this.elevation,
    // 高亮狀態下, 按鈕底部陰影效果的偏移量, double
    this.highlightElevation,
    // 禁用狀態下, 按鈕底部陰影效果的偏移量, double
    this.disabledElevation,
    // 內邊距
    this.padding,
    // 按鈕的形狀
    this.shape,
    this.clipBehavior = Clip.none,
    this.materialTapTargetSize,
    this.animationDuration,
    // 按鈕的最小寬度
    this.minWidth,
    // 按鈕的高度
    this.height,
    // 子widget
    this.child,
})
複製代碼

onPressed

按鈕觸發時觸發的函數,若是不設置此屬性Button爲不可用狀態

onPressed: () => print('被點擊了'),
複製代碼

textTheme

按鈕字體的主題, 在onPressed不爲空的時候纔有效果

/// 三個取值
ButtonTextTheme.normal
ButtonTextTheme.accent
ButtonTextTheme.primary
複製代碼

image

colorBrightness

設置按鈕的字體亮度, 取值分別是Brightness.lightBrightness.darks

image

padding

內邊距,其接收值的類型是EdgeInsetsGeometry類型的,EdgeInsetsGeometry是一個抽象類, 只能使用其子類EdgeInsets來實現

padding: EdgeInsets.all(10)
複製代碼

shape

  • 設置按鈕的形狀,其接收值是ShapeBorder類型,ShapeBorder也是一個抽象類
  • ShapeBorder的子類中比較經常使用的幾個以下所示
    • BeveledRectangleBorder 帶斜角的長方形邊框
    • CircleBorder 圓形邊框
    • RoundedRectangleBorder 圓角矩形
    • StadiumBorder 兩端是半圓的邊框
// 帶斜角的長方形邊框
const BeveledRectangleBorder({
    // 邊框的樣式 
    this.side = BorderSide.none,
    // 圓角大小
    this.borderRadius = BorderRadius.zero,
})

// 圓形邊框
const CircleBorder({ 
    this.side = BorderSide.none 
})

// 圓角矩形
const RoundedRectangleBorder({
    this.side = BorderSide.none,
    this.borderRadius = BorderRadius.zero,
})

// 兩端是半圓的邊框
const StadiumBorder({ 
    this.side = BorderSide.none 
})

// 邊框樣式的設置
const BorderSide({
    // 邊框顏色, 默認黑色 
    this.color = const Color(0xFF000000),
    // 邊框寬度, 默認1.0
    this.width = 1.0,
    // 邊框樣式, solid: 實線邊框(默認值), none: 不顯示邊框
    this.style = BorderStyle.solid,
})
複製代碼

下面就來看一下shape的配置和使用, 設置默認狀態(即全部的邊框樣式和圓角都是默認值)的效果以下

image

children: <Widget>[
  // BeveledRectangleBorder
  RaisedButton(
    child: Text('BeveledRectangleBorder'),
    onPressed: () => print('RaisedButton'),
    shape: BeveledRectangleBorder(
      borderRadius: BorderRadius.all(Radius.circular(10)),
      side: BorderSide(
        color: Colors.red,
        width: 2,
        style: BorderStyle.solid
      )
    ),
  ),
  RaisedButton(
    child: Icon(Icons.supervisor_account, color: Colors.green, size: 40),
    onPressed: () => print('RaisedButton'),
    padding: EdgeInsets.all(10),
    shape: CircleBorder(
      side: BorderSide(
        color: Colors.red,
        width: 2,
        style: BorderStyle.solid
      )
    ),
  ),
  RaisedButton(
    child: Text('RoundedRectangleBorder'),
    onPressed: () => print('RaisedButton'),
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.all(Radius.circular(10)),
      side: BorderSide(
        color: Colors.red,
        width: 2,
        style: BorderStyle.solid
      )
    ),
  ),
  RaisedButton(
    child: Text('StadiumBorder'),
    onPressed: () => print('RaisedButton'),
    shape: StadiumBorder(
      side: BorderSide(
        color: Colors.red,
        width: 2,
        style: BorderStyle.solid
      )
    ),
  ),
],
複製代碼

上述代碼是分別設置圓角和邊框後的代碼, 效果以下

image

RaisedButton

  • RaisedButton即"漂浮"按鈕,它默認帶有陰影和灰色背景。按下後陰影會變大
  • RaisedButton繼承自MaterialButton, 相關屬性和父類同樣
RaisedButton(
    child: Text('RaisedButton'),
    onPressed: () => print('RaisedButton'),
)
複製代碼

FlatButton

  • FlatButton即扁平按鈕,默認背景透明並不帶陰影。按下後,會有背景色
  • RaisedButton繼承自MaterialButton, 相關屬性和父類同樣
FlatButton(
    child: Text('FlatButton'),
    onPressed: () => print('FlatButton'),
)
複製代碼

OutlineButton

  • OutlineButton默認有一個邊框,不帶陰影且背景透明。按下後,邊框顏色會變亮、同時出現背景和陰影(較弱)
  • RaisedButton繼承自MaterialButton, 相關屬性和父類同樣
OutlineButton(
    child: Text('OutlineButton'),
    onPressed: () => print('OutlineButton'),
)
複製代碼

IconButton

IconButton是一個可點擊的Icon,不包括文字,默認沒有背景,點擊後會出現背景

// 繼承自StatelessWidget
class IconButton extends StatelessWidget {
  const IconButton({
    Key key,
    // 按鈕的大小
    this.iconSize = 24.0,
    // 內邊距
    this.padding = const EdgeInsets.all(8.0),
    // 按鈕中圖片的對齊方式
    this.alignment = Alignment.center,
    // 圖片按鈕的圖片Icon
    @required this.icon,
    // 背景色
    this.color,
    // 高亮狀態下的背景色
    this.highlightColor,
    // 按鈕按下時, 水波紋的顏色
    this.splashColor,
    // 禁用狀態下, 按鈕的背景色
    this.disabledColor,
    // 點擊事件
    @required this.onPressed,
    // String, 描述按鈕按下時的描述文本, 須要長按才能出現(黑框顯示文本)
    this.tooltip
  })
}
複製代碼

使用示例

IconButton(
    icon: Icon(Icons.mail_outline, color:Colors.orange, size: 40),
    color: Colors.yellow,
    iconSize: 100,
    alignment: Alignment.topLeft,
    onPressed: () => print('IconButton'),
    tooltip: 'titanjun.top',
)
複製代碼

圖文按鈕

每個繼承自MaterialButton的按鈕Widget都有一個工廠構造函數, 返回一個圖片在左, 文字在右的按鈕

factory RaisedButton.icon({
    // 這裏包含MaterialButton的全部屬性
    ....
    // 圖片Widget
    @required Widget icon,
    // 文字Widget
    @required Widget label,
  })
  
factory FlatButton.icon({
    ....
    @required Widget icon,
    @required Widget label,
  })
  
factory OutlineButton.icon({
    ....
    @required Widget icon,
    @required Widget label,
  })
  
// 使用示例
RaisedButton.icon(
  label: Text('data'),
  icon: Icon(Icons.mail),
  onPressed: () => {},
),
複製代碼

單選開關和複選框

  • Material widgets庫中提供了Material風格的單選開關Switch和複選框Checkbox,它們都是繼承自StatelessWidget
  • 它們自己不會保存當前選擇狀態,因此通常都是在父widget中管理選中狀態
  • 當用戶點擊SwitchCheckbox時,它們會觸發onChanged回調,咱們能夠在此回調中處理選中狀態改變邏輯
// Switch屬性
const Switch({
    Key key,
    // Switch的狀態值, true開啓, false關閉
    @required this.value,
    // Switch改變狀態所執行的操做
    @required this.onChanged,
    // 開啓狀態下選項條的顏色
    this.activeColor,
    // 開啓狀態下圓球的顏色
    this.activeTrackColor,
    // 關閉狀態下選項條的顏色
    this.inactiveThumbColor,
    // 關閉狀態下圓球的顏色
    this.inactiveTrackColor,
    // 設置開啓狀態下圓球的圖片
    this.activeThumbImage,
    // 設置關閉狀態下圓球的圖片
    this.inactiveThumbImage,
    // 設置Switch的尺寸樣式, padded: 建議大小48, shrinkWrap: 可能的最小尺寸
    this.materialTapTargetSize,
})

// Checkbox屬性
const Checkbox({
    Key key,
    // Switch的狀態值, true選中, false未選中
    @required this.value,
    // 若是爲 true,那麼複選框的值能夠是 true,false 或 null
    // 若是爲false(默認值), 那麼只有true和false兩種狀態
    this.tristate = false,
    // 改變狀態時執行的函數
    @required this.onChanged,
    // 選中時的顏色
    this.activeColor,
    // 設置Checkbox的尺寸樣式, padded: 建議大小48, shrinkWrap: 可能的最小尺寸
    this.materialTapTargetSize,
})
複製代碼

使用代碼

children: <Widget>[
  Switch(
    value: false,
    onChanged: (value) {},
    activeColor: Colors.red,
    activeTrackColor: Colors.yellow,
    inactiveThumbColor: Colors.blue,
    inactiveTrackColor: Colors.cyan,
    materialTapTargetSize: MaterialTapTargetSize.shrinkWrap
  ),
  Checkbox(
    value: true,
    onChanged: (value) { },
    activeColor: Colors.orange,
    tristate: true,
  )
],
複製代碼

image


歡迎您掃一掃下面的微信公衆號,訂閱個人博客!

微信公衆號
相關文章
相關標籤/搜索