天天看點

Flutter-常用的weiget介紹(一)内容widget介紹Widget介紹

Widget介紹

widget可以把它看作成一個元件(或者是一個單元),在Flutter中,就是通過widget來建構項目的UI,Flutter有一套豐富、強大的基礎widget,下面是比較常用的Widget

runApp函數

接受給定的Widget并使用其作為widget根

Stateless widgets

是不可變的,這意味着它們的屬性不能改變——所有的值都是 final

Stateful widgets

持有的狀态可能在 widget 生命周期中發生變化,實作一個 stateful widget 至少需要兩個類:

  • 一個 StatefulWidget 類;
  • 一個 State 類;

StatefulWidget 類本身是不變的,但是 State 類在widget 生命周期中始終存在,通過State裡面修改屬性的值進而達到頁面的重新渲染;

如果需要變化需要重新建立。StatefulWidget可以儲存自己的狀态。那問題是既然widget都是immutable的,怎麼儲存狀态?其實Flutter是通過引入了State來儲存狀态。當State的狀态改變時,

能重新建構本節點以及孩子的Widget樹來進行UI變化。注意:如果需要主動改變State的狀态,需要通過setState()方法進行觸發,單純改變資料是不會引發UI改變的

内容widget

Text 文本

該 widget 可讓建立一個帶格式的文本

示例demo1 (直接new Text的方式來設定)

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new Text(
        // 顯示文本
         "Hello world",
        //  對齊方式
         textAlign: TextAlign.center,
         overflow: TextOverflow.ellipsis,
        //  設定樣式
         style: TextStyle(color:Colors.pink)
      ),
    );
  }
}
           

示例demo2 (通過 Text.rich)

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Text.rich(
        TextSpan(
          // 預設文本
          text: 'Hello',
          style: TextStyle(fontSize: 20),//設定預設的大小
          children: <TextSpan>[//裡面可以放多個文本TextSpan,可以單獨給每一個文本進行樣式的設定和内容的設定
            TextSpan(text:'第一個顯示的文本',style:TextStyle(fontSize: 24,fontWeight: FontWeight.bold)),
            TextSpan(text:'第二個顯示的文本',style:TextStyle(fontWeight: FontWeight.bold,fontStyle: FontStyle.italic))
          ]
        )
      )
    );
  }
}
           

Text元件常用屬性詳解

Text(this.data, {
    Key key,
    this.style,
    this.textAlign,//文本方向(左(TextAlign.left)|右(TextAlign.right)|中(TextAlign.center)|兩端對齊(TextAlign.justify)|開始(TextAlign.start)|結束(TextAlign.end))
    this.textDirection,//文本對齊方式(文本從右到左(TextDirection.rtl)|文本從左到右(TextDirection.ltr))
    this.locale,
    this.softWrap,//文本是否能換行
    this.overflow,//文本溢出的處理方式(剪切(TextOverflow.clip)|隐藏(TextOverflow.fade)|省略号(TextOverflow.ellipsis))
    this.textScaleFactor,//文本字型縮放倍數
    this.maxLines,//文本最多能顯示多少行
    this.semanticsLabel,
  }) : assert(data != null),
       textSpan = null,
       super(key: key);
           

TextStyle 常用屬性詳解

源碼中 style及構造函數

const TextStyle({
    this.inherit = true,//是否将null值替換為祖先文本樣式中的值(例如,在TextSpan樹中)。如果為false,則沒有顯式值的屬性将恢複為預設值:白色,字型大小為10像素,采用無襯線字型
    this.color,//文本顔色
    this.backgroundColor,//背景顔色
    this.fontSize,//文字大小
    this.fontWeight,// 是否加粗,利用FontWeight 來設定
    this.fontStyle,// 字型風格,利用FontStyle 來設定
    this.letterSpacing,//字母間距,整數拉開字母距離,若是負數則拉近字母距離
    this.wordSpacing,//單詞間距,同上
    this.textBaseline,//用于對齊文本的水準線
    this.height,//文本行高,為字型大小的倍數
    this.locale,//文本國際化
    this.foreground,//字型前景
    this.background,//文本背景
    this.shadows,// 文本的陰影可以利用清單疊加處理,例如shadows: [Shadow(color:Colors.black,offset: Offset(6, 3), blurRadius: 10)], color即陰影的顔色, offset即陰影相對文本的偏移坐标,blurRadius即陰影的模糊程度,越小越清晰
    this.fontFeatures,
    this.decoration,//文字的線性裝飾,比如 underline 下劃線, lineThrough删除線
    this.decorationColor,//文本裝飾線的顔色
    this.decorationStyle,//文本裝飾線的樣式,比如 dashed 虛線
    this.decorationThickness,
    this.debugLabel,//這種文本樣式的可讀描述,此屬性僅在調試建構中維護
    String fontFamily,
    List<String> fontFamilyFallback,
    String package,
  }) : fontFamily = package == null ? fontFamily : 'packages/$package/$fontFamily',
       _fontFamilyFallback = fontFamilyFallback,
       _package = package,
       assert(inherit != null),
       assert(color == null || foreground == null, _kColorForegroundWarning),
       assert(backgroundColor == null || background == null, _kColorBackgroundWarning);
           

Image 圖檔

如果要顯示圖檔,則需要使用 Image 控件,支援 JPEG、PNG、GIF、Animated GIF、WebP、Animated WebP、BMP 和 WBMP 等格式。Image 可以顯示檔案、資源包或者網絡圖檔,當圖

标加載完後會在 界面顯示;圖檔具有寬度、高度、顔色過濾器(類似于 Android 中的 tint color)、fit 模式、重複模式 等屬性。 和 Android 中 ImageView 的屬性差不多

加載網絡圖檔

  • 在頁面通過 Image.network 來進行引用
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primaryColor: Colors.white,
      ),
      // 通過 network 來進行網絡圖檔的引入
      home: Image.network('http://www.itcast.cn/2018czgw/images/logo.png')
    );
  }
}
           

加載資源圖檔

加載的是項目中資源目錄的檔案

  • 在項目根目錄建立assets檔案夾,在裡面建立images檔案夾,裡面放入資源圖檔
  • pubspec.yaml

    檔案中配置資源目錄
flutter:
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  assets:
    - assets/images/1.png
           
  • 在頁面 通過 Image.asset 來進行引入
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primaryColor: Colors.white,
      ),
      // 通過asset 來進行資源圖檔的引入
      home: new Image.asset('assets/images/logo.png')
    );
  }
}
           

加載本地圖檔

加載的是手機的本地存儲的圖檔

Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;//Android來說 /data/user/0/com.example.fluttersample/cache   

Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;//Android來說 /data/user/0/com.example.fluttersample/app_flutter

String storageDir = (await getExternalStorageDirectory()).path;//Android來說 /storage/emulated/0/   sd卡的路徑
           
  • 操作SD卡需要申請相應的權限,在

    AndroidManifest.xml

    檔案中添加如下
<!-- 寫權限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 讀權限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
           
Flutter-常用的weiget介紹(一)内容widget介紹Widget介紹
  • 編寫代碼,這裡擷取sd卡目錄是異步的,我們需要通過,async和await來配合使用,在方法中擷取到路徑之後,通過setState來更新頁面
    • 這裡需要更新資料,我們需要建立一個類 繼承 StateFulWidget
    • 在createState方法中傳回 ImageState
    • 建立ImageState 繼承 State
    • 在bulde方法中調用擷取SD卡路徑的方法
    • 在build return 裡面調用 Image.file() 來引入本地檔案
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primaryColor: Colors.white,
        ),
        home: new ImageWidget());
  }
}

class ImageWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return new ImageState();
  }
}

class ImageState extends State<ImageWidget> {
  String _storageStr = '';
  @override
  Widget build(BuildContext context) {
    // 判斷如果為空,那麼調用擷取sd卡路徑的方法
    if(_storageStr=='')  _getLocalFile();
    print(_storageStr);
    // TODO: implement build
    // 通過加載 本地檔案的方式來 引入圖檔,如果要設定屬性,接着寫在後面就好,詳細的屬性在後面有講解
    return new Image.file(new File('$_storageStr/Pictures/logo.png',color:Colors.pink));
  }
  /**
   * 封裝方法,擷取sd卡路徑是異步方法
   */
  _getLocalFile() async {
    String storageDir = (await getExternalStorageDirectory()).path;
    // 擷取到了之後,通過 setState方式來更新頁面資料,注意,setSate 隻能在 state裡面進行調用
    setState(() {
      this._storageStr = storageDir;
    });
  }
}
           

記憶體中加載圖檔

用于從記憶體裡(Uint8List)顯示圖檔

// Uint8List圖檔
new Image.memory(bytes),
           

圖檔的其他參數

屬性名 說明
semanticLabel 圖像的語義描述
excludeFromSemantics 預設false 是否啟用圖像的語義描述
width 寬度 一般結合 ClipOval 才能看到效果
height 高度 一般結合 ClipOval 才能看到效果
color 背景色
colorBlendMode 使圖像與背景色混合 模式
fit

BoxFit.fill:全圖顯示,圖檔會被拉伸,并充滿父容器。

BoxFit.contain:全圖顯示,顯示原比例,可能會有空隙。

BoxFit.cover:顯示可能拉伸,可能裁切,充滿(充滿容器不變形)。

BoxFit.fitWidth:寬度充滿(橫向充滿),顯示可能拉伸,可能裁切。

BoxFit.fitHeight :高度充滿(豎向充滿),顯示可能拉伸,可能裁切。

BoxFit.scaleDown:效果和 contain 差不多,但是此屬性不允許顯示超過源圖檔大小,可小不可大

alignment 對齊方式
repeat

平鋪

ImageRepeat.repeat : 橫向和縱向都進行重複,直到鋪滿整個畫布

ImageRepeat.repeatX: 橫向重複,縱向不重複。

ImageRepeat.repeatY:縱向重複,橫向不重複。

centerSlice 設定拉伸部位,不能和fit一同使用 圖檔大于等于容器時 屬性無效
matchTextDirection

預設false

官方翻譯:是否在TextDirection的方向上繪制圖像

gaplessPlayback

預設false

官方翻譯:當圖像提供者發生變化時,是繼續顯示舊圖像,預設不顯示

filterQuality

預設FilterQuality.low

官方翻譯:圖像過濾器的品質級别。(渲染模式的品質)