今天的主題會圍繞在三個常用的元件Image
(圖片), Text
(文字), Button
(按鈕)
並用它們來實作
好的,那我們就開始吧!
Image.asset
, Image.network
, Image.file
...fit
, scale
, loadingBuilder
, frameBuilder
引用放到專案中的圖檔
assets
資料架assets/
放入圖片,例如 assets/test.png
pubspec.yaml
中的flutter:
區塊下方指定圖片位置
flutter:
uses-material-design: true
# 新增圖片,將asset圖片加入專案以便引用
assets:
- assets/test.png
Image(image: AssetImage('assets/test.png'));
// or
Image.asset('assets/test.png')
AssetImage
是一種ImageProvider
,用於提供特定路徑的圖像資源,Image.asset
constructor內部就是使用AssetImage
取得圖片的。由於這個方法是將圖檔加入專案中一起打包成應用程式,會造成App佔用空間變大,需仔細斟酌。
Image.network('https://WEB_SOURCE')
Image.file(File('/storage/FILE_SOURCE'),)
引用時需填入該檔案在裝置上的位置fit
: 調整圖像大小的策略, 通常使用BoxFit
BoxFit.contain
:圖片小於外框時,在不變形的情況下盡可能地填滿外框BoxFit.cover
:圖片大於外框時,在不變形的情況下盡可能塞進外框,並將多餘的部分裁切BoxFit.fill
: 以圖片塞滿外框,可能造成變形BoxFit.fitHeight
:讓圖片垂直方向完全展示,不管水平方向是否有被裁切BoxFit.fitWidth
:讓圖片水平方向完全展示,不管垂直方向是否有被裁切BoxFit.none
:維持原圖BoxFit.scaleDown
:將圖片對準框中心並縮小圖片直到全圖皆可以完整顯示scale
: 對圖片進行縮放。輸入的數值代表在圖片長寬不變的情況下,增加垂直和水平的像素的倍數。例如scale:2.0
代表此圖片範圍內,水平和垂直的像素數量皆變為兩倍,因此圖片本身看起來會縮小。
loadingBuilder:設定在圖片在載入時所要顯示的元件
如官網案例,顯示CircularProgressIndicator(載入中的轉圈圈元件),並指定這個轉圈圈的進度會比照載入圖片的百分比來進行:
Image.network(
'https://flutter.github.io/assets-for-api-docs/assets/widgets/falcon.jpg',
fit: BoxFit.cover,
loadingBuilder:(
BuildContext context,
Widget child,
ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) {
return child;
}
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes!
: null,
),
);
}
)
frameBuilder: 設定圖片載入時的動畫效果
如官方案例,建立過場動畫為透明淡出
Image.network(
'https://flutter.github.io/assets-for-api-docs/assets/widgets/puffin.jpg',
frameBuilder: (BuildContext context, Widget child, int? frame,
bool wasSynchronouslyLoaded) {
if (wasSynchronouslyLoaded) {
return child;
}
return AnimatedOpacity(
opacity: frame == null ? 0 : 1,
duration: const Duration(seconds: 1),
curve: Curves.easeOut,
child: child,
);
},
),
更多Image的介紹,詳見Image
class
style
參數設置文字的樣式Text(
'Hello, $_name! How are you?',
textAlign: TextAlign.center, // 將文字對齊置中
overflow: TextOverflow.ellipsis, // 文字超出外框時會省略超出的部分改為'...'
style: const TextStyle(fontWeight: FontWeight.bold),
)
當一組文字中需要有多種複雜的樣式,就可以使用RichText
來呈現
如下例,'Hello bold World!'中的'bold'要特別用粗體顯示,那我可以把這個文字組寫在RichText
中,另外定義'bold'的樣式
RichText(
text: TextSpan(
text: 'Hello ',
style: DefaultTextStyle.of(context).style,
children: const <TextSpan>[
TextSpan(text: 'bold', style: TextStyle(fontWeight: FontWeight.bold)),
TextSpan(text: ' world!'),
],
),
)
更多關於Text的介紹,詳見Text
Widgets
按鈕是一種點擊之後會觸發特定行為的組件,依照樣式分為TextButton, ElevatedButton和OutlinedButton
透過style
設定按鈕樣式,onPress
設定點擊後要執行的函式,並透過child
來決定它的子元件(顯示在按鈕內部的組件)。
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {},
child: const Text('TextButton'),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 9.0, textStyle: const TextStyle(fontSize: 20)),
onPressed: () {},
child: const Text('ElevatedButton'),
),
OutlinedButton(
style: OutlinedButton.styleFrom(
textStyle: const TextStyle(fontSize: 20)),
onPressed: () {},
child: const Text('OutlinedButton'),
)
],
),
TextButton
, ElevatedButton
, OutlinedButton
加入圖片區塊,取得線上的圖片位址並使用Image.network()
Image.network('https://apod.nasa.gov/apod/image/2209/WaterlessEarth2_woodshole_2520.jpg')
加入圖片載入時顯示的畫面:指示載入進度的圓圈
Image.network(
'https://apod.nasa.gov/apod/image/2209/WaterlessEarth2_woodshole_2520.jpg',
loadingBuilder:(
BuildContext context,
Widget child,
ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) {
return child;
}
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes!
: null,
),
);
}
)
)
使用ElevatedButton
加入「add to favorite」按鈕
ElevatedButton(
onPressed: () {
print('add to favorite');
},
child: const Text('favorite')),
加入文字說明區塊:複製今日APOD的說明並以Text呈現
const Text(
"How much of planet Earth is made of water? Very little, actually. Although oceans of water cover about 70 percent of Earth's surface, these oceans are shallow compared to the Earth's radius. The featured illustration shows what would happen if all of the water on or near the surface of the Earth were bunched up into a ball. The radius of this ball would be only about 700 kilometers, less than half the radius of the Earth's Moon, but slightly larger than Saturn's moon Rhea which, like many moons in our outer Solar System, is mostly water ice. The next smallest ball depicts all of Earth's liquid fresh water, while the tiniest ball shows the volume of all of Earth's fresh-water lakes and rivers. How any of this water came to be on the Earth and whether any significant amount is trapped far beneath Earth's surface remain topics of research.",
style: TextStyle(fontSize: 12, color: Colors.blueGrey),
)
Image
, ElevatedButton
和Text
。但是畫面上有一個施工區塊,這是由於我們的畫面排版不當、有組件在版面上被切到,flutter於debug版本給我們的提示。Day11
相關commitImage
:圖片組件
Image.asset
:載入專案內附帶的圖片Image.network
:載入網路上的圖片Image.file
:載入本地裝置的圖片fit
:圖片塑形的方式scale
:圖片縮放loadingBuilder
:載入圖片時的畫面frameBuilder
:載入圖片時的動畫Text
Text
:文字組件RichText
:多重樣式的文字組合組件Button
TextButton
:文字按鈕ElevatedButton
:立體按鈕OutlinedButton
:框線按鈕