1. 程式人生 > >Flutter 基礎元件之 Image

Flutter 基礎元件之 Image

正所謂一圖勝千言,一張意思清晰明瞭的圖片勝過 N 句廢話,所以圖片的展示是相當重要的,Image 是 Flutter 用於展示圖片的控制元件,它可以載入專案內的圖片、手機儲存中的圖片以及直接從網路載入圖片,不用再整合圖片載入框架就可以載入網路圖片這就很方便了。

1 構造方法

Image({Key key, @required ImageProvider image, String semanticLabel, bool excludeFromSemantics: false, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, FilterQuality filterQuality: FilterQuality.low })

建立一個 Image 元件,其中一個必傳引數為 ImageProvider,它指定了圖片是從哪裡載入,是從專案中還是網路中等等。 

Image.asset(String name, { Key key, AssetBundle bundle, String semanticLabel, bool excludeFromSemantics: false, double scale, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, String package, FilterQuality filterQuality: FilterQuality.low })

建立一個從專案中的資源目錄載入圖片的 Image,其實就相當於第一種構造方法指定 ImageProvider 為 AssetImage。

Image.file(File file, { Key key, double scale: 1.0, String semanticLabel, bool excludeFromSemantics: false, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, FilterQuality filterQuality: FilterQuality.low })

建立一個從手機儲存目錄載入圖片的 Image,其實就相當於第一種構造方法指定 ImageProvider 為 FlieImage。

Image.memory(Uint8List bytes, { Key key, double scale: 1.0, String semanticLabel, bool excludeFromSemantics: false, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, FilterQuality filterQuality: FilterQuality.low })

應該是建立一個從記憶體或者位元組流載入圖片的 Image,其實就相當於第一種構造方法指定 ImageProvider 為 MemoryImage。

Image.network(String src, { Key key, double scale: 1.0, String semanticLabel, bool excludeFromSemantics: false, double width, double height, Color color, BlendMode colorBlendMode, BoxFit fit, AlignmentGeometry alignment: Alignment.center, ImageRepeat repeat: ImageRepeat.noRepeat, Rect centerSlice, bool matchTextDirection: false, bool gaplessPlayback: false, FilterQuality filterQuality: FilterQuality.low, Map<String, String> headers })

建立一個從網路載入圖片的 Image,其實就相當於第一種構造方法指定 ImageProvider 為 NetworkImage。

其實後四種構造方法就相當於對第一種構造方法進行了封裝,不用傳入 ImageProvider 而已,但是仍要傳入圖片路徑,所以說也沒省多大事,我比較傾向用第一種構造方法。

 

2 常用屬性

image:從哪裡載入圖片,值為一個 ImageProvider 物件,ImageProvider 的實現類有 AssetBundleImageProvider(AssetImage 繼承自它)、FileImage、MemoryImage、NetworkImage,需要注意的是,如果選擇 AssetImage 從資源目錄中載入圖片,需在 pubspec.yaml 配置檔案中配置 assets 目錄:

必須是上面的層級關係,但是感覺從資源目錄載入圖片老有問題,有時候顯示不出來但又不報錯,可以試試目錄後面跟上具體檔名,即:

但是這樣每張圖片都得配置,未免太過麻煩,而選擇 NetworkImage 從網路載入圖片就簡單多了,只需要指定圖片的 url 即可。

width heigh:寬和高,不必贅述。

alignment:如果圖片沒有填充滿容器的話,圖片的對齊方式,值為一個 AlignmentGeometry 物件,Alignment 是它的一個實現類,可選值同 Container 的 Alignment 取值一樣。
    Alignment.topLeft:垂直靠頂部水平靠左對齊。
    Alignment.topCenter:垂直靠頂部水平居中對齊。
    Alignment.topRight:垂直靠頂部水平靠右對齊。
    Alignment.centerLeft:垂直居中水平靠左對齊。
    Alignment.center:垂直和水平居中都對齊。
    Alignment.centerRight:垂直居中水平靠右對齊。
    Alignment.bottomLeft:垂直靠底部水平靠左對齊。
    Alignment.bottomCenter:垂直靠底部水平居中對齊。
    Alignment.bottomRight:垂直靠底部水平靠右對齊。
    除了上面的常量之外,還可以建立 Alignment 物件指定 x、y 偏移量。

color:在圖片上設定顏色,值為一個 Color 物件,會覆蓋 image 指定的圖片,如果也設定了 colorBlendMode 屬性,則會與 image 混合產生特殊效果。

colorBlendMode:顏色混合模式,類似 BoxDecoration 的 backgroundBlendMode。

excludeFromSemantics:是否啟用影象的語義描述。

filterQuality:影象過濾器的質量級別(使用該屬性還沒看到效果,後面用到了再研究)。

fit:圖片的縮放方式,類似 Android 中 ImageView 的 scaleType,可選值有:
    BoxFit.none:將圖片的內容按原大小居中顯示。
    BoxFit.contain:將圖片的內容完整居中顯示,通過按比例縮小或原來的 size 使得圖片寬/高等於或小於元件的寬/高,類似 Android 的 centerInside。
    BoxFit.cover:按比例放大圖片的 size 居中顯示,類似 Android 的 centerCrop。
    BoxFit.fill:把圖片不按比例放大/縮小到元件的大小顯示,類似 Android 的 fitXY。
    BoxFit.fitHeight:把圖片的高按照元件的高顯示,寬等比例放大/縮小。
    BoxFit.fitWidth:把圖片的寬按照元件的寬顯示,高等比例放大/縮小。
    BoxFit.scaleDown:如果圖片寬高大於元件寬高,則讓圖片內容完全居中顯示,此時同 contain,如果圖片寬高小於元件寬高,則按圖片原大小居中顯示,此時同 none。

centerSlice:該屬性用於 .9 圖的中心拉伸,值為一個 Rect 物件,應該就是拉伸區域,我在使用該屬性的時候只有當 fit 設定為 contain 和 fill 時才看到了效果,該屬性應該也是用於圖形變換,不常用。

gaplessPlayback:當 ImageProvider 發生變化後,重新載入圖片的過程中,原圖片的展示是否保留。true 表示保留,false 表示不保留,直接空白等待下一張圖片載入。

matchTextDirection:該屬性值表示圖片的方向是否跟隨文字的方向,其實就相當於左右翻轉,true 表示翻轉,false 表示不翻轉,但是要想該屬性生效,必須使用 Directionality 元件包裹 Image 元件,如下面程式碼:

new Directionality(
    textDirection: TextDirection.rtl,
    child: new Image(
        image: new NetworkImage(imgUrl),
        matchTextDirection: true,
    ),
)

上面程式碼中的 textDirection 屬性值為 TextDirection.rtl,即從右向左,然後 Image 元件的圖片方向跟隨文字方向也是從右向左,即相當於左右翻轉的效果。

repeat:如果圖片沒填充滿容器的話,圖片的重複方式,可選值有:
    ImageRepeat.noRepeat:不重複。
    ImageRepeat.repeat:X、Y 軸都重複。
    ImageRepeat.repeatX:只在 X 軸重複。
    ImageRepeat.repeatY:只在 Y 軸重複。

semanticLabel:影象的語義描述,類似 Android 中 ImageView 的 contentDescription 屬性。

 

下面是一個設定了上面部分屬性的 Image 元件的 demo:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
//    var imgUrl =
//        "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1545191828292&di=caef0d773e90142191de9fc5f5871cef&imgtype=0&src=http%3A%2F%2Fimg.mp.sohu.com%2Fq_mini%2Cc_zoom%2Cw_640%2Fupload%2F20170807%2Fb008bbf3df1b490d85e3ff3152ea898e_th.jpg";
    var imgUrl =
        "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1545790666&di=45beff1e706ea81d796d2268553c9e6f&imgtype=jpg&er=1&src=http%3A%2F%2Fp1.music.126.net%2FfydScGuKzV4GFdqeCMKhxQ%3D%3D%2F109951163178133629.jpg%3Fparam%3D180y180";
    return MaterialApp(
      //是否顯示 debug 標籤
      debugShowCheckedModeBanner: false,
      title: "Image",
      home: Scaffold(
        appBar: new AppBar(
          title: new Text("Image"),
        ),
        body: new Container(
          color: new Color(0xFFFF0000),
          //子元件
          child: new Image(
            //從資源目錄中載入圖片,需在 pubspec.yaml 配置檔案中配置 assets 目錄
            //flutter:
            //  assets:
            //    - assets/images/
            //必須是上面的層級關係,但是感覺從資源目錄載入圖片老有問題,有時候顯示不出來但又不報錯,可以試試目錄後面跟上具體檔名,即
            //flutter:
            //  assets:
            //    - assets/images/iverson.jpg
            //但是這樣每張圖片都得配置,未免太過麻煩
//            image: new AssetImage("assets/images/iverson.jpg"),
            //從網路載入圖片,非常容易,不用配置,而且只要有網就沒什麼問題
            image: new NetworkImage(imgUrl),
            width: 300,
            height: 200,
            //如果圖片沒有填充滿容器的話,圖片的對齊方式,值為一個 AlignmentGeometry 物件,Alignment 是它的一個實現類
            //可選值同 Container 的 Alignment 取值一樣。
            //Alignment.topLeft:垂直靠頂部水平靠左對齊
            //Alignment.topCenter:垂直靠頂部水平居中對齊
            //Alignment.topRight:垂直靠頂部水平靠右對齊
            //Alignment.centerLeft:垂直居中水平靠左對齊
            //Alignment.center:垂直和水平居中都對齊
            //Alignment.centerRight:垂直居中水平靠右對齊
            //Alignment.bottomLeft:垂直靠底部水平靠左對齊
            //Alignment.bottomCenter:垂直靠底部水平居中對齊
            //Alignment.bottomRight:垂直靠底部水平靠右對齊
            //除了上面的常量之外,還可以建立 Alignment 物件指定 x、y 偏移量
            alignment: Alignment.center,
            //在圖片上設定顏色,值為一個 Color 物件,會覆蓋 image 指定的圖片,如果也設定了 colorBlendMode 屬性,則會與 image 混合產生特殊效果
            color: new Color(0xFFFFFF00),
            //顏色混合模式,類似 BoxDecoration 的 backgroundBlendMode
            colorBlendMode: BlendMode.darken,
//            excludeFromSemantics: true,
//            filterQuality: FilterQuality.high,
            //圖片的縮放方式,類似 Android 中 ImageView 的 scaleType,可選值有:
            //BoxFit.none:將圖片的內容按原大小居中顯示。
            //BoxFit.contain:將圖片的內容完整居中顯示,通過按比例縮小或原來的 size 使得圖片寬/高等於或小於元件的寬/高,類似 Android 的 centerInside。
            //BoxFit.cover:按比例放大圖片的 size 居中顯示,類似 Android 的 centerCrop。
            //BoxFit.fill:把圖片不按比例放大/縮小到元件的大小顯示,類似 Android 的 fitXY。
            //BoxFit.fitHeight:把圖片的高按照元件的高顯示,寬等比例放大/縮小。
            //BoxFit.fitWidth:把圖片的寬按照元件的寬顯示,高等比例放大/縮小。
            //BoxFit.scaleDown:如果圖片寬高大於元件寬高,則讓圖片內容完全居中顯示,此時同 contain,如果圖片寬高小於元件寬高,則按圖片原大小居中顯示,此時同 none。
            fit: BoxFit.contain,
//            centerSlice:new Rect.fromCircle(center: Offset(100.0, 100.0), radius: 10.0),
//            gaplessPlayback: true,
            matchTextDirection: true,
            //如果圖片沒填充滿容器的話,圖片的重複方式,可選值有:
            //ImageRepeat.noRepeat:不重複
            //ImageRepeat.repeat:X、Y 軸都重複
            //ImageRepeat.repeatX:只在 X 軸重複
            //ImageRepeat.repeatY:只在 Y 軸重複
            repeat: ImageRepeat.noRepeat,
//            semanticLabel: "",
          ),
        ),
      ),
    );
  }
}

 

執行效果如下:

 

3 總結

Flutter 載入網路圖片比起 Android 要略微簡單一些,不過要是載入專案包中的圖片可能還需要一些配置,這個可以是利弊皆有,最常用的 Text 和 Image 元件看過後發現其實並不難,還有什麼理由不繼續,加油少年。