前面兩篇文章介紹了
Flutter win
環境的安裝,以及利用listview
實現了簡單佈局。(這篇文章篇幅有點長,讀完大概需要8.88
分鐘)
Flutter 入門實現 ListView 列表頁面以及收藏頁面
Flutter 環境搭建以及填坑指南(Win10 系統且已有 Android 開發環境
這篇文章主要介紹以下內容:
3. ListView 點選事件,單個 widget 點選事件
在這篇文章Flutter 入門實現 ListView 列表頁面以及收藏頁面中雖然實現了一個列表,但是怎麼實現的還沒仔細研究,現在就先從研究 ListView
的實現開始吧。
先看一下之前實現的效果:
實現的程式碼主要是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
,這個語言之前沒學過,這裡就先不深入學習了,網上有比較好的這個博主 戀貓月亮寫的系列的文章寫的很好。我這裡就只寫實現上面圖片中展示的效果。
1. ListView 能實現什麼效果?
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, ], ), );
}
}複製程式碼
2. widget 如何新增到 ListView 中?
上面的虛擬碼中在構建一個有狀態的widget
的時候會重寫 build
方法,在該方法中的 body
返回我們實現的 widget
即可。
3. ListView 點選事件,單個 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);
}
});
}, ),複製程式碼
4. widget 如何垂直、水平擺放?
最常見的佈局模式之一是垂直或水平排列widget。在
Flutter
可以使用行Row
水平排列widget
,並使用列Column
垂直排列widget
。 同時,每個孩子本身可以是一個Row
或一個Column
,依此類推。以下示例顯示如何在行或列內巢狀行或列。
通過下面兩張圖片可以學到在實現佈局時如何拆分:參考連結 widget 佈局
在控制行或列對齊其子項時使用mainAxisAlignment
( 主軸 ) 和crossAxisAlignment
( 橫軸 ) 屬性來。 對於行(Row)
來說,**主軸是水平方向,橫軸垂直方向。**對於列(Column)
來說,主軸垂直方向,橫軸水平方向。
MainAxisAlignment 和 CrossAxisAlignment 類提供了很多控制對齊的常量.MainAxisAlignment
-
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<
<wbr>MainAxisAlignment>
:根據值得大小來分配空間,值越大空間分配越多。
CrossAxisAlignment 屬性相同的基本和上面介紹的一樣,就不贅述了。
- baseline → const CrossAxisAlignment:基線對齊
- center → const CrossAxisAlignment
- end → const CrossAxisAlignment
- start → const CrossAxisAlignment
- stretch → const CrossAxisAlignment:子
widget
填充橫軸(CrossAxisAlignment),如果橫軸上子widget
很多,會使橫軸變得很擠。 - values → const List<
<wbr>CrossAxisAlignment>
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), ], );
// ...
}複製程式碼
5. 圖片、Icon、Text widget 的簡單使用
這些都是基礎控制元件使用起來很簡單的,可檢視這個文件介紹:基礎 Widget
在學習完上面的內容我們可以實現出目前的樣式了:
實現列表功能,以及一個可滾動的詳情頁面,頂部的標題是 listview 傳遞過去的單詞。
文章篇幅過長了,這裡就不介紹上圖的實現過程了,原始碼地址如下覺得還湊合的給個star
,好讓我繼續堅持寫下去~原始碼地址
看原始碼或者上文中不理解的可以聯絡我,我會知無不言的。
本文完。