滾動列表效果圖
第一步,先還是用建立工程的辦法讓Android Studio自動生成一段hello world程式碼,我們基於這段程式碼去擴充套件實現。
import 'package:flutter/material.dart';void main() => runApp(new MyApp());class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: 'Welcome to Flutter', home: new Scaffold( appBar: new AppBar( title: const Text('Welcome to Flutter'), ), body: const Center( child: const Text('Hello World'), ), ), ); }}
首先看看如何引入第三方SDK/API的Lib庫吧,只有學會了如何引用第三方庫,才能讓自己的App瞬間變得龐大起來,程式設計師們從來都不會萬丈高樓平地起,而是喜歡站在別人的肩膀上(lib庫上)。這裡我們用引用一個單詞庫為例,現在pubspec.yaml檔案裡的dependencies裡增加一行: english_words: ^3.1.0 ,告訴編譯系統我們需要引用這個庫檔案了。然後點選下圖右上角的 Pub get按鈕,Android Studio就會自動去下載依賴庫。
引用庫檔案
我們把hello world程式碼修改一下,讓app不再死板的只輸出一個hello world,而是能隨機輸出一些讓人意想不到的單詞。貼出程式碼,line 4 我們從第三方庫裡隨機獲取一個單詞,line 13我們把這個單詞輸出到介面上,替代固定不變的hello world。
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { final wordPair = new WordPair.random(); // 新增了這一行 return new MaterialApp( title: 'Welcome to Flutter', home: new Scaffold( appBar: new AppBar( title: new Text('Welcome to Flutter'), ), body: new Center( // 這裡把之前的 "const" 換成了 "new". //child: const Text('Hello World'), // 我們不用這樣的方式生成文字了 child: new Text(wordPair.asPascalCase), // 這是新的文字生成方式 ), ), ); }}
我們的App是不是稍微有趣了點?這還不夠,接下來我們讓我們的App能有記憶,關掉退出再進來時,還能記住之前的狀態,顯示上一次的資訊。首先我們定義一個有狀態的Widget,取名為 RandomWords。
class RandomWords extends StatefulWidget { @override RandomWordsState createState() => new RandomWordsState();}
class RandomWordsState extends State<RandomWords> { @override // 新增程式碼片段 - 開始 ... Widget build(BuildContext context) { final WordPair wordPair = new WordPair.random(); return new Text(wordPair.asPascalCase); } // ... 新增的程式碼片段 - 結束}
然後我們修改MyApp裡的程式碼,見 line 13,直接把RandomWords這個有狀態的Widget輸出到介面去顯示。這樣當這個介面被關閉再回來時,還能保持之前的單詞顯示狀態。
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { final WordPair wordPair = new WordPair.random(); // 刪掉本行 return new MaterialApp( title: 'Welcome to Flutter', home: new Scaffold( appBar: new AppBar( title: new Text('Welcome to Flutter'), ), body: new Center( //child: new Text(wordPair.asPascalCase), // 修改本行內容 child: new RandomWords(), // 修改成本行程式碼 ), ), ); }}
到現在,我們這個App既能隨機顯示單詞,還能有記憶了,這還不夠,現在我們來讓它顯示一個滾動列表吧。在RandomWordsState裡增加兩行程式碼,定義一個List變數,一個字型樣式變數(變數前面加下劃線表示變數是pravite的)。
class RandomWordsState extends State<RandomWords> { // 新增如下兩行 final List<WordPair> _suggestions = <WordPair>[]; final TextStyle _biggerFont = const TextStyle(fontSize: 18.0); ...}
然後我們構建一個帶List的Widget,先看下面line 31,我們構建了一個每行顯示一個單詞的Widget函式,取名為_buildRow(),這個構建函式比較簡單,就是定義了一個text元素。然後構建一個顯示多行單詞的列表Widget函式,取名為_buildSuggestions(),這個函式稍微複雜一些,它用了一個itemBuilder的回撥函式,自動迴圈建立列表的每一個item,從而隨著使用者滾動,生成一個無限可下拉的列表。
Widget _buildSuggestions() { return new ListView.builder( padding: const EdgeInsets.all(16.0), // 對於每個建議的單詞對都會呼叫一次 itemBuilder, // 然後將單詞對新增到 ListTile 行中 // 在偶數行,該函式會為單詞對新增一個 ListTile row. // 在奇數行,該函式會新增一個分割線的 widget,來分隔相鄰的詞對。 // 注意,在小螢幕上,分割線看起來可能比較吃力。 itemBuilder: (BuildContext _context, int i) { // 在每一列之前,新增一個1畫素高的分隔線widget if (i.isOdd) { return new Divider(); } // 語法 "i ~/ 2" 表示i除以2,但返回值是整形(向下取整) // 比如 i 為:1, 2, 3, 4, 5 時,結果為 0, 1, 1, 2, 2, // 這可以計算出 ListView 中減去分隔線後的實際單詞對數量 final int index = i ~/ 2; // 如果是建議列表中最後一個單詞對 if (index >= _suggestions.length) { // ...接著再生成10個單詞對,然後新增到建議列表 _suggestions.addAll(generateWordPairs().take(10)); } return _buildRow(_suggestions[index]); } );}Widget _buildRow(WordPair pair) { return new ListTile( title: new Text( pair.asPascalCase, style: _biggerFont, ), );}
最後,我們更新MyApp的build方法,見line 10,不再是直接顯示一個text了,而是顯示一個_buildSuggestions的widget,這樣就把列表放置在主介面了。
@override Widget build(BuildContext context) { //final wordPair = new WordPair.random(); // 刪掉 ... //return new Text(wordPair.asPascalCase); // ... 這兩行 return new Scaffold ( // 程式碼從這裡... appBar: new AppBar( title: new Text('Startup Name Generator'), ), body: _buildSuggestions(), ); // ... 新增到這裡 }
我們執行一下看看結果,在Flutter開發過程中,不用每次重新點Run按鈕,而是可以點閃電按鈕(熱過載hot reload),可以看到幾秒鐘就能出來新的結果了,這點比Android開發高效多了。點選閃電圖示後,如下所示,我們可以看到列表展示出來了。我們用滑鼠模擬滾動手勢進行操作,可以看到不盡長江滾滾來,新單詞一直往上跑。
執行結果
至此,我們第一個Flutter的正式App就一氣呵成了,功能相對來說還是比較複雜和充實的,是可以拿得出手了。