首先, 獲取代碼:
接下來,將圖像添加到示例中:
第一步是將布局拆分成基本的元素:
首先,確定更大的元素。在這個(gè)例子中,四個(gè)元素排列成一列:一個(gè)圖像,兩個(gè)行和一個(gè)文本塊
接下來,繪制每一行。第一行稱其為標(biāo)題部分,有三個(gè)子項(xiàng):一列文字,一個(gè)星形圖標(biāo)和一個(gè)數(shù)字。它的第一個(gè)子項(xiàng),列,包含2行文字。 第一列占用大量空間,所以它必須包裝在Expanded widget中。
第二行稱其為按鈕部分,也有3個(gè)子項(xiàng):每個(gè)子項(xiàng)都是一個(gè)包含圖標(biāo)和文本的列。
一旦拆分好布局,最簡單的就是采取自下而上的方法來實(shí)現(xiàn)它。為了最大限度地減少深度嵌套布局代碼的視覺混淆,將一些實(shí)現(xiàn)放置在變量和函數(shù)中。
首先,構(gòu)建標(biāo)題部分左邊欄。將Column(列)放入Expanded中會拉伸該列以使用該行中的所有剩余空閑空間。 設(shè)置crossAxisAlignment屬性值為CrossAxisAlignment.start,這會將該列中的子項(xiàng)左對齊。
將第一行文本放入Container中,然后底部添加8像素填充。列中的第二個(gè)子項(xiàng)(也是文本)顯示為灰色。
標(biāo)題行中的最后兩項(xiàng)是一個(gè)紅色的星形圖標(biāo)和文字“41”。將整行放在容器中,并沿著每個(gè)邊緣填充32像素
這是實(shí)現(xiàn)標(biāo)題行的代碼。
Note: If you have problems, you can check your code against lib/main.dart
on GitHub.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
Widget titleSection = new Container(
padding: const EdgeInsets.all(32.0),
child: new Row(
children: [
new Expanded(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
new Container(
padding: const EdgeInsets.only(bottom: 8.0),
child: new Text(
'Oeschinen Lake Campground',
style: new TextStyle(
fontWeight: FontWeight.bold,
),
),
),
new Text(
'Kandersteg, Switzerland',
style: new TextStyle(
color: Colors.grey[500],
),
),
],
),
),
new Icon(
Icons.star,
color: Colors.red[500],
),
new Text('41'),
],
),
);
//...
}
提示: 將代碼粘貼到應(yīng)用程序中時(shí),縮進(jìn)可能會變形。您可以通過右鍵單擊,選擇 Reformat with dartfmt 來在IntelliJ中修復(fù)此問題?;蛘?,在命令行中,您可以使用 dartfmt。
提示: 為了獲得更快的開發(fā)體驗(yàn),請嘗試使用Flutter的熱重載功能。 熱重載允許您修改代碼并查看更改,而無需完全重新啟動(dòng)應(yīng)用程序。 IntelliJ的Flutter插件支持熱重載,或者您可以從命令行觸發(fā)。 有關(guān)更多信息,請參閱Hot Reloads vs 應(yīng)用程序重新啟動(dòng)。
按鈕部分包含3個(gè)使用相同布局的列 - 上面一個(gè)圖標(biāo),下面一行文本。該行中的列平均分布行空間, 文本和圖標(biāo)顏色為主題中的primary color,它在應(yīng)用程序的build()方法中設(shè)置為藍(lán)色:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
//...
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
//...
}
由于構(gòu)建每個(gè)列的代碼幾乎是相同的,因此使用一個(gè)嵌套函數(shù),如buildButtonColumn,它會創(chuàng)建一個(gè)顏色為primary color,包含一個(gè)Icon和Text的 Widget 列。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
//...
Column buildButtonColumn(IconData icon, String label) {
Color color = Theme.of(context).primaryColor;
return new Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
new Icon(icon, color: color),
new Container(
margin: const EdgeInsets.only(top: 8.0),
child: new Text(
label,
style: new TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: color,
),
),
),
],
);
}
//...
}
構(gòu)建函數(shù)將圖標(biāo)直接添加到列(Column)中。將文本放入容器以在文本上方添加填充,將其與圖標(biāo)分開。
通過調(diào)用函數(shù)并傳遞icon和文本來構(gòu)建這些列。然后在行的主軸方向通過 MainAxisAlignment.spaceEvenly 平均的分配每個(gè)列占據(jù)的行空間。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
//...
Widget buttonSection = new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
buildButtonColumn(Icons.call, 'CALL'),
buildButtonColumn(Icons.near_me, 'ROUTE'),
buildButtonColumn(Icons.share, 'SHARE'),
],
),
);
//...
}
將文本放入容器中,以便沿每條邊添加32像素的填充。softwrap屬性表示文本是否應(yīng)在軟換行符(例如句點(diǎn)或逗號)之間斷開。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
//...
Widget textSection = new Container(
padding: const EdgeInsets.all(32.0),
child: new Text(
'''
Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese Alps. Situated 1,578 meters above sea level, it is one of the larger Alpine Lakes. A gondola ride from Kandersteg, followed by a half-hour walk through pastures and pine forest, leads you to the lake, which warms to 20 degrees Celsius in the summer. Activities enjoyed here include rowing, and riding the summer toboggan run.
''',
softWrap: true,
),
);
//...
}
四列元素中的三個(gè)現(xiàn)在已經(jīng)完成,只剩下圖像部分。該圖片可以在Creative Commons許可下在線獲得, 但是它非常大,且下載緩慢。在步驟0中,您已經(jīng)將該圖像包含在項(xiàng)目中并更新了pubspec文件,所以現(xiàn)在可以從代碼中直接引用它:
body: new ListView(
children: [
new Image.asset(
'images/lake.jpg',
height: 240.0,
fit: BoxFit.cover,
),
// ...
],
)
BoxFit.cover 告訴框架,圖像應(yīng)該盡可能小,但覆蓋整個(gè)渲染框
在最后一步,你將上面這些組裝在一起。這些widget放置到ListView中,而不是列中,因?yàn)樵谛≡O(shè)備上運(yùn)行應(yīng)用程序時(shí),ListView會自動(dòng)滾動(dòng)。
//...
body: new ListView(
children: [
new Image.asset(
'images/lake.jpg',
width: 600.0,
height: 240.0,
fit: BoxFit.cover,
),
titleSection,
buttonSection,
textSection,
],
),
//...
更多建議: