一,概述
Image(圖片組件)是顯示圖像的組件,一個顯示圖片的widget,支持圖像格式:JPEG,PNG,GIF,動畫GIF,WebP,動畫WebP,BMP和WBMP。 Image組件有多種構造函數:
- new Image: 從ImageProvider獲取圖像。
- new Image.asset: 加載本地圖片文件。
- new Image.file: 加載本地圖片文件。
- new Image.network: 加載網絡圖片。
- new Image.memory: 加載Uint8List資源圖片。
二,繼承關系
- Object > Diagnosticablet > DiagnosticableTreet > Widgett > StatefulWidgett > Image
三,構造方法
- new Image: 從ImageProvider獲取圖像。
- 類名構造方法,它指定了圖片是從哪里加載,是從項目中還是網絡中等等。
const Image({Key key,@required this.image,this.frameBuilder,this.loadingBuilder,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,}) : assert(image != null),assert(alignment != null),assert(repeat != null),assert(filterQuality != null),assert(matchTextDirection != null),super(key: key);
- 類名構造方法,它指定了圖片是從哪里加載,是從項目中還是網絡中等等。
- new Image.asset: 加載資源圖片文件。
- 命名構造方法,用於使用key從AssetBundle獲取圖像。就是加載項目資源目錄中的圖片,加入圖片后會增大打包的包體體積,用的是相對路徑。
- 其實就相當於第一種構造方法指定 ImageProvider 為 AssetImage
- 沿襲的是 iOS 的圖片風格,分為 1x,2x,3x,具體做法是在項目的根目錄下創建兩個文件夾,如下圖所示:
-
然后需要在
pubspec.yaml
文件中聲明一下:flutter: # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true assets: - images/logo.png - images/2.0x/logo.png - images/3.0x/logo.png
-
用法如下:
new Image.asset('images/logo.png')
- 構造方法
-
Image.asset( String name, { Key key, AssetBundle bundle, this.frameBuilder, this.semanticLabel, this.excludeFromSemantics = false, double scale, 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, String package, this.filterQuality = FilterQuality.low, }) : image = scale != null ? ExactAssetImage(name, bundle: bundle, scale: scale, package: package) : AssetImage(name, bundle: bundle, package: package), loadingBuilder = null, assert(alignment != null), assert(repeat != null), assert(matchTextDirection != null), super(key: key);
- new Image.file: 加載本地圖片文件。
- 命名構造方法,加載本地圖片,就是加載本地文件中的圖片,這個是一個絕對路徑,跟包體無關。 用於從File獲取圖像
- 其實就相當於第一種構造方法指定 ImageProvider 為 FlieImage
- 加載一個本地
File
圖片,比如相冊中的圖片,用法如下
new Image.file(new File('/storage/xxx/xxx/test.jpg'))
- 構造函數
Image.file( File file, { Key key, double scale = 1.0, this.frameBuilder, 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, }) : image = FileImage(file, scale: scale), loadingBuilder = null, assert(alignment != null), assert(repeat != null), assert(filterQuality != null), assert(matchTextDirection != null), super(key: key);
- new Image.network: 加載網絡圖片。
- 命名構造方法,用於從URL地址獲取圖像。意思就是你需要加入一段http://xxxx.xxx的這樣的網絡路徑地址。
new Image.network('http://n.sinaimg.cn/sports/2_img/upload/cf0d0fdd/107/w1024h683/20181128/pKtl-hphsupx4744393.jpg')
- 其實就相當於第一種構造方法指定 ImageProvider 為 NetworkImage。
-
有的時候我們需要像Android那樣使用一個占位圖或者圖片加載出錯時顯示某張特定的圖片,這時候需要用到 FadeInImage 這個組件:
//第一種方法是加載一個本地的占位圖
new FadeInImage.assetNetwork( placeholder: 'images/logo.png', image: imageUrl, width: 120, fit: BoxFit.fitWidth, )
//第二種是加載一個透明的占位圖,但是需要注意的是,這個組件是不可以設置加載出錯顯示的圖片的
new FadeInImage.memoryNetwork( placeholder: kTransparentImage, image: imageUrl, width: 120, fit: BoxFit.fitWidth, )//另一種方法可以使用第三方 package 的 CachedNetworkImage 組件:CachedNetworkImage 組件中的占位圖是一個 Widget,這樣的話就可以自定義了,你想使用什么樣的組件進行占位都行,同樣加載出錯的占位圖也是一個組件,也可以自己定義;該組件也是通過緩存來加載圖片的。
new CachedNetworkImage(
width: 120,
fit: BoxFit.fitWidth,
placeholder: new CircularProgressIndicator(),
imageUrl: imageUrl,
errorWidget: new Icon(Icons.error),
) - 構造函數
Image.network( String src, { Key key, double scale = 1.0, this.frameBuilder, this.loadingBuilder, 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, Map<String, String> headers, }) : image = NetworkImage(src, scale: scale, headers: headers), assert(alignment != null), assert(repeat != null), assert(matchTextDirection != null), super(key: key);
- 命名構造方法,用於從URL地址獲取圖像。意思就是你需要加入一段http://xxxx.xxx的這樣的網絡路徑地址。
- new Image.memory: 加載Uint8List資源圖片。
- 用來將一個
byte
數組加載成圖片
new Image.memory(bytes)
- 命名構造函數
Image.memory( Uint8List bytes, { Key key, double scale = 1.0, this.frameBuilder, 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, }) : image = MemoryImage(bytes, scale: scale), loadingBuilder = null, assert(alignment != null), assert(repeat != null), assert(matchTextDirection != null), super(key: key);
- 用來將一個
四,參數詳解
- image:
從哪里加載圖片,值為一個 ImageProvider 對象,ImageProvider 的實現類有 AssetBundleImageProvider(AssetImage 繼承自它)、FileImage、MemoryImage、NetworkImage,需要注意的是,如果選擇 AssetImage 從資源目錄中加載圖片,需在 pubspec.yaml 配置文件中配置 assets 目錄:上面有介紹 - 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。
- BlendModel枚舉值
-
switch (blendMode) {
case kCGBlendModeNormal: {
strMsg = @"kCGBlendModeNormal: 正常;也是默認的模式。前景圖會覆蓋背景圖";
break;
}
case kCGBlendModeMultiply: {
strMsg = @"kCGBlendModeMultiply: 正片疊底;混合了前景和背景的顏色,最終顏色比原先的都暗";
break;
}
case kCGBlendModeScreen: {
strMsg = @"kCGBlendModeScreen: 濾色;把前景和背景圖的顏色先反過來,然后混合";
break;
}
case kCGBlendModeOverlay: {
strMsg = @"kCGBlendModeOverlay: 覆蓋;能保留灰度信息,結合kCGBlendModeSaturation能保留透明度信息,在imageWithBlendMode方法中兩次執行drawInRect方法實現我們基本需求";
break;
}
case kCGBlendModeDarken: {
strMsg = @"kCGBlendModeDarken: 變暗"; //將線條色變為黑色,背景色設置為目的色
break;
}
case kCGBlendModeLighten: {
strMsg = @"kCGBlendModeLighten: 變亮";
break;
}
case kCGBlendModeColorDodge: {
strMsg = @"kCGBlendModeColorDodge: 顏色變淡";
break;
}
case kCGBlendModeColorBurn: {
strMsg = @"kCGBlendModeColorBurn: 顏色加深"; //線條顏色(原本)加深,背景色設置為目的色
break;
}
case kCGBlendModeSoftLight: {
strMsg = @"kCGBlendModeSoftLight: 柔光";
break;
}
case kCGBlendModeHardLight: {
strMsg = @"kCGBlendModeHardLight: 強光"; //全為目的色
break;
}
case kCGBlendModeDifference: {
strMsg = @"kCGBlendModeDifference: 插值";
break;
}
case kCGBlendModeExclusion: {
strMsg = @"kCGBlendModeExclusion: 排除";
break;
}
case kCGBlendModeHue: {
strMsg = @"kCGBlendModeHue: 色調";
break;
}
case kCGBlendModeSaturation: {
strMsg = @"kCGBlendModeSaturation: 飽和度";
break;
}
case kCGBlendModeColor: {
strMsg = @"kCGBlendModeColor: 顏色"; //感覺將圖片線條色設置為白色,背景色設置為目的色,之后再再圖片上加一個有透明度的目的色
break;
}
case kCGBlendModeLuminosity: {
strMsg = @"kCGBlendModeLuminosity: 亮度";
break;
}
//Apple額外定義的枚舉
//R: premultiplied result, 表示混合結果
//S: Source, 表示源顏色(Sa對應透明度值: 0.0-1.0)
//D: destination colors with alpha, 表示帶透明度的目標顏色(Da對應透明度值: 0.0-1.0)
case kCGBlendModeClear: {
strMsg = @"kCGBlendModeClear: R = 0"; //1.清空(如果圖標背景色為白色則為全白)
break;
}
case kCGBlendModeCopy: {
strMsg = @"kCGBlendModeCopy: R = S"; //2全色覆蓋整個圖片
break;
}
case kCGBlendModeSourceIn: {
strMsg = @"kCGBlendModeSourceIn: R = S*Da"; //3.線條變色
break;
}
case kCGBlendModeSourceOut: {
strMsg = @"kCGBlendModeSourceOut: R = S*(1 - Da)"; //4.背景變為目的色,線條自動變為白色(比如圖標線條原為藍色,會自動變為白色)
break;
}
case kCGBlendModeSourceAtop: {
strMsg = @"kCGBlendModeSourceAtop: R = S*Da + D*(1 - Sa)"; //5.線條變色,目前感覺和SourceIn效果一致
break;
}
case kCGBlendModeDestinationOver: {
strMsg = @"kCGBlendModeDestinationOver: R = S*(1 - Da) + D"; //6.背景色變為目的色,線條色不變
break;
}
case kCGBlendModeDestinationIn: {
strMsg = @"kCGBlendModeDestinationIn: R = D*Sa;能保留透明度信息"; //7.只看到線條色(本色),無其他顏色
break;
}
case kCGBlendModeDestinationOut: {
strMsg = @"kCGBlendModeDestinationOut: R = D*(1 - Sa)"; //8.空白什么都沒喲
break;
}
case kCGBlendModeDestinationAtop: {
strMsg = @"kCGBlendModeDestinationAtop: R = S*(1 - Da) + D*Sa"; //9.會把整個矩形的背景填充目的色(如圖9系列)原色保留
break;
}
case kCGBlendModeXOR: {
strMsg = @"kCGBlendModeXOR: R = S*(1 - Da) + D*(1 - Sa)"; //10.線條變白,背景色變為目的色
break;
}
case kCGBlendModePlusDarker: {
strMsg = @"kCGBlendModePlusDarker: R = MAX(0, (1 - D) + (1 - S))"; //11.線條變為黑色, 背景色變為目的色
break;
}
case kCGBlendModePlusLighter: {
strMsg = @"kCGBlendModePlusLighter: R = MIN(1, S + D)(最后一種混合模式)"; //12.線條變為白色(混合色:如color為紅色,就是偏粉色的白,有一定透明度的感覺)
break;
}
default: {
break;
}
- 顏色混合模式,類似 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
該屬性用於的中心拉伸,值為一個 Rect 對象,應該就是拉伸區域,我在使用該屬性的時候只有當 fit 設置為 contain 和 fill 時才看到了效果,該屬性應該也是用於圖形變換,不常用。- 使用方法
//centerSlice = Rect.fromLTRB(l, t, r, b)
Image.network(
"https://upload.jianshu.io/users/upload_avatars/3884536/d847a50f1da0.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240",
width: 400,
height: 400,
fit: BoxFit.contain,
centerSlice: Rect.fromLTWH(10, 10, 10, 10),
) 效果
- Rect效果默認
- centerSlice處理
- 使用方法
- gaplessPlayback(無間隙播放)
- 當image provider 發生變化時,顯示新圖片的過程中,如果true則保留舊圖片直至顯示出新圖片為止;如果false,則顯示新圖片的過程中,空白,不保留舊圖片。
- 當image provider 發生變化時,顯示新圖片的過程中,如果true則保留舊圖片直至顯示出新圖片為止;如果false,則顯示新圖片的過程中,空白,不保留舊圖片。
- repeat:
如果圖片沒填充滿容器的話,圖片的重復方式,可選值有:
- ImageRepeat.noRepeat:不重復。
-
ImageRepeat.repeat:X、Y 軸都重復。
-
ImageRepeat.repeatX:只在 X 軸重復。
-
ImageRepeat.repeatY:只在 Y 軸重復。
- ImageRepeat.noRepeat:不重復。
- semanticLabel:
圖像的語義描述,類似 Android 中 ImageView 的 contentDescription 屬性。
五,示例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:'Image組件學習', ), ), ), ); } }
六,實現圓角/圓形圖片
-
圓角
- 使用裁剪來實現圖片圓角:
new ClipRRect( child: Image.network( imageUrl, scale: 8.5, fit: BoxFit.cover, ), borderRadius: BorderRadius.only( topLeft: Radius.circular(20), topRight: Radius.circular(20), ), )
- 使用裁剪來實現圖片圓角:
-
使用邊框來實現圖片圓角:
new Container( width: 120, height: 60, decoration: BoxDecoration( shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(10.0), image: DecorationImage( image: NetworkImage(imageUrl), fit: BoxFit.cover), ), )
- 需要注意的是,使用邊框實現的時候要注意設置
fit
屬性,不然效果也是有問題的,當然了你還可以使用Material
組件來實現。
-
圓形
圓形圖片用得最多的應該是頭像之類的,這種同樣有多種方式可以實現,下面我也舉兩個例子使用裁剪實現圓形圖片:
new ClipOval( child: Image.network( imageUrl, scale: 8.5, ), )
使用CircleAvatar來實現圓形圖片:
new CircleAvatar( backgroundImage: NetworkImage(imageUrl), radius: 50.0, )
七,官方地址
- 官方文檔--Image