前面兩篇文章介紹了
Flutter win
環境的安裝,以及利用listview
實現了簡單佈局。(這篇文章篇幅有點長,讀完大概須要8.88
分鐘)html
Flutter 入門實現 ListView 列表頁面以及收藏頁面git
Flutter 環境搭建以及填坑指南(Win10 系統且已有 Android 開發環境 github
這篇文章主要介紹如下內容:bash
2. widget 如何添加到 ListView 中?app
3. ListView 點擊事件,單個 widget 點擊事件框架
4. ( 重點 ) widget 如何垂直、水平擺放?less
5. 圖片、Icon、Text widget 的簡單使用dom
在這篇文章Flutter 入門實現 ListView 列表頁面以及收藏頁面中雖然實現了一個列表,可是怎麼實現的還沒仔細研究,如今就先從研究 ListView
的實現開始吧。ide
先看一下以前實現的效果:
實現的代碼主要是RandomWordsState
類中的下面代碼:
return new ListTile(
// 單詞佈局
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
// 喜歡當心心佈局
trailing: new Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
// ListView item 的點擊事件
onTap: () {
// 通知框架狀態已經改變
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
);
複製代碼
從上面的代碼中能夠看出實現這個列表主要就是操做了 ListTile
這個 Widget
,那麼咱們看看這個ListTile
的構造方法都提供了上面功能吧!註釋都寫在代碼中了~
/// Requires one of its ancestors to be a [Material] widget.
const ListTile({
Key key,
// 在列表的左邊添加的 widget(如文末圖中的左邊圖片)
this.leading,
// 標題
this.title,
// 副標題
this.subtitle,
// 在列表的右邊添加的 widget(如文末圖中的右邊心形 icon)
this.trailing,
// 若是 isThreeLine 爲 true, subtitle 則不能爲 null,默認爲 false
// 若是 副標題爲空則列表平鋪一行顯示,若是 副標題 不爲空,則副標題所佔的佈局是兩行
// 若是 isThreeLine = true 則副標題能夠顯示三行。
this.isThreeLine = false,
// bool 類型,默認爲false ,若是爲 true 則 ListTile 在垂直方向是密集型擺放
//(具體效果待後面去實現,這裏只是看了註釋後的理解)
this.dense,
// 內容的邊距
this.contentPadding,
// item 是否能點擊
this.enabled = true,
// item 的點擊事件
this.onTap,
// item 的長按事件
this.onLongPress,
// item 是否選中標記
this.selected = false,
})
複製代碼
flutter
的開發語言是dart
,這個語言以前沒學過,這裏就先不深刻學習了,網上有比較好的這個博主 戀貓月亮 寫的系列的文章寫的很好。我這裏就只寫實現上面圖片中展現的效果。
ListView 不只能夠實現列表佈局,還能夠實現 Android 中的 ScrollView 的功能。關於 滾動的 widget 還有其餘的實現,可參考**可滾動Widget簡介**
實現列表功能,若是是符合ListTile
的樣式,直接使用ListTile
實現很方便。(目前還沒學到如何實現多佈局,後面學習再寫一篇)
實現ScrollView
功能,直接在build
方法的body
中添加咱們的 widget
。僞代碼以下:
定義了一個
DetailScreen
詳情頁面,繼承了StatelessWidget
,在build
方法中返回了頁面的內容:appBar
是標題欄,body
是顯示的內容
class DetailScreen extends StatelessWidget {
// Declare a field that holds the pair
final WordPair pair;
// In the constructor, require a pair
DetailScreen({Key key, @required this.pair}) : super(key: key);
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
// 接收傳遞過來的單詞作標題名字
title: new Text("${pair.asPascalCase}"),
),
// 使用 ListView 作滾動列表
body: new ListView(
children: [
// 顯示網絡圖片
new Image.asset(
'images/wali.jpg',
width: 600.0,
height: 240.0,
fit: BoxFit.cover,
),
// 標題行(文末有實現效果)
titleSection,
// 按鈕行(文末有實現效果)
buttonSection,
// 描述文本(文末有實現效果)
textSection,
],
),
);
}
}
複製代碼
上面的僞代碼中在構建一個有狀態的widget
的時候會重寫 build
方法,在該方法中的 body
返回咱們實現的 widget
便可。
若是ListView
使用ListTile
實現列表的話,直接使用ListTile
中的 onTap
實現列表點擊效果。若是不是用ListTile
實現,那就使用單個widget
的點擊事件吧。
widget
的若是有onTap
方法能夠直接調用該方法便可實現,若是沒有該方法,則須要使用GestureDetector
來實現點擊效果,例如上圖中的心形喜歡點擊事件,僞代碼實現以下:
關於
GestureDetector
可參考該文章 手勢識別GestureDetector
trailing: new GestureDetector(
// 心形喜歡 icon
child: new Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
// 點擊事件
onTap: (){
// 通知框架狀態已經改變
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
),
複製代碼
最多見的佈局模式之一是垂直或水平排列widget。在
Flutter
可使用行Row
水平排列widget
,並使用列Column
垂直排列widget
。 同時,每一個孩子自己能夠是一個Row
或一個Column
,依此類推。如下示例顯示如何在行或列內嵌套行或列。
經過下面兩張圖片能夠學到在實現佈局時如何拆分: 參考連接 widget 佈局
在控制行或列對齊其子項時使用mainAxisAlignment
( 主軸 ) 和crossAxisAlignment
( 橫軸 ) 屬性來。 對於行(Row)
來講,**主軸是水平方向,橫軸垂直方向。**對於列(Column)
來講,主軸垂直方向,橫軸水平方向。
center → const MainAxisAlignment :子 widget
在主軸方向上居中顯示
end → const MainAxisAlignment :子 widget
在主軸方向上居右邊顯示,若是是水平方向,那麼由 TextDirection 來決定end
是在左邊(ltr)仍是在右邊(rtl)。若是是豎直方向,那麼由 VerticalDirection 來決定end
是在上邊(up)仍是在下邊(down)
start → const MainAxisAlignment:子 widget
在主軸方向上居左邊顯示,同理 end
。
spaceAround → const MainAxisAlignment:子widget
中的第一個和最後一個widget
距離邊的距離是它與中間的距離的一半。(這裏比較抽象,後期實現效果了會順帶講解)
spaceBetween → const MainAxisAlignment:子widget
中的第一個和最後一個貼邊,剩餘的子widget
將中間的空間平分。
spaceEvenly → const MainAxisAlignment:子widget
將佈局空間徹底平分
values → const List<
CrossAxisAlignment 屬性相同的基本和上面介紹的同樣,就不贅述了。
widget
填充橫軸(CrossAxisAlignment),若是橫軸上子widget
不少,會使橫軸變得很擠。Expanded widget
Expanded widget,能夠將widget的大小設置爲適和行或列
Expanded
有個屬性flex(彈性係數)
,默認狀況下,每一個widget的彈性係數爲1,也就是會鋪滿布局。
例如實現:三張圖片水平鋪滿屏幕,便可使用Expanded
包裹Image
而後設置flex:1
,不設置也行,由於默認flex
就是1
僞代碼以下:
body: new Center(
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
new Expanded(
child: new Image.asset('images/pic1.jpg'),
),
new Expanded(
child: new Image.asset('images/pic2.jpg'),
),
new Expanded(
child: new Image.asset('images/pic3.jpg'),
),
複製代碼
彙集 widgets
默認狀況下,行或列沿着其主軸會盡量佔用儘量多的空間,但若是要將孩子緊密彙集在一塊兒,能夠將
mainAxisSize
設置爲MainAxisSize.min
。
例如實現:五個星形圖標圖標緊湊在一塊兒。
僞代碼以下:class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
var packedRow = new Row(
mainAxisSize: MainAxisSize.min,
children: [
new Icon(Icons.star, color: Colors.green[500]),
new Icon(Icons.star, color: Colors.green[500]),
new Icon(Icons.star, color: Colors.green[500]),
new Icon(Icons.star, color: Colors.black),
new Icon(Icons.star, color: Colors.black),
],
);
// ...
}
複製代碼
這些都是基礎控件使用起來很簡單的,可查看這個文檔介紹:基礎 Widget
在學習完上面的內容咱們能夠實現出目前的樣式了:
實現列表功能,以及一個可滾動的詳情頁面,頂部的標題是 listview 傳遞過去的單詞。
文章篇幅過長了,這裏就不介紹上圖的實現過程了,源碼地址以下 以爲還湊合的給個star
,好讓我繼續堅持寫下去~ 源碼地址
看源碼或者上文中不理解的能夠聯繫我,我會知無不言的。
本文完。