1. 程式人生 > >Flutter互動篇——使用者互動,路由和主題切換實現

Flutter互動篇——使用者互動,路由和主題切換實現

本文介紹Flutter的使用者互動方式和路由操作,以及簡單的主題切換操作。
我們將為上篇文章Flutter控制元件篇(Stateful widget)——ListView新增心形 ❤️圖示,為這個圖示加入點選收藏的功能。

然後增加互動,當用戶點選列表中的條目,切換其”收藏”狀態,並將該詞對新增到或移除出”收藏夾”。

為列表新增心形 ❤️圖示

新增一個_saved Set(集合),到 RandomWordsState,這個集合儲存使用者喜歡(收藏)的單詞對。 在這裡,Set 比 List 更合適,因為 Set 中不允許重複的值。

class RandomWordsState
extends State<RandomWords> {
final List<WordPair> _suggetions = <WordPair>[]; final TextStyle _biggerFont = const TextStyle(fontSize: 18.0); // 新增一個 _saved Set(集合),儲存使用者喜歡(收藏)的單詞對。不要用 List ,因為 Set 中不允許重複的值。 final Set<WordPair> _saved=new Set<WordPair>(); …… }

在_buildRow方法中新增alreadySaved來檢查確保單詞對還沒有新增到收藏夾中。

Widget _buildRow(WordPair pair){
//    新增 alreadySaved 來檢查確保單詞對還沒有新增到收藏夾中
 final bool alreadySaved=_saved.contains(pair);
}

同時在_buildRow()中, 新增一個心形 ❤️圖示到 ListTiles以啟用收藏功能。接下來,我們就可以給心形 ❤️圖示新增互動能力了。

Widget _buildRow(WordPair pair){
//    新增 alreadySaved 來檢查確保單詞對還沒有新增到收藏夾中
 final bool alreadySaved=
_saved.contains(pair); return new ListTile( title: new Text( pair.asPascalCase, style: _biggerFont, ), //在 _buildRow() 中, 新增一個心形 ❤️圖示到 ListTiles以啟用收藏功能。接下來,你就可以給心形 ❤️圖示新增互動能力了。 trailing: new Icon( alreadySaved?Icons.favorite:Icons.favorite_border, color: alreadySaved?Colors.red:null, ), }

至此,我們給列表的每一項都添加了心形圖片,接下來就要給他們新增互動功能

為心形 ❤️圖示增加互動

我們將為剛剛的心形 ❤️圖示增加互動,當用戶點選列表中的條目,切換其”收藏”狀態,並將該詞對新增到或移除出”收藏夾”。

我們在_buildRow中讓心形 ❤️圖示變得可以點選。如果單詞條目已經新增到收藏夾中, 再次點選它將其從收藏夾中刪除。當心形 ❤️圖示被點選時,函式呼叫setState()通知框架狀態已經改變。

_buildRow中增加onTap方法》

Widget _buildRow(WordPair pair){
//    新增 alreadySaved 來檢查確保單詞對還沒有新增到收藏夾中
 final bool alreadySaved=_saved.contains(pair);

   return new ListTile(
     title: new Text(
       pair.asPascalCase,
       style: _biggerFont,
     ),
//      在 _buildRow() 中, 新增一個心形 ❤️圖示到 ListTiles以啟用收藏功能。接下來,你就可以給心形 ❤️圖示新增互動能力了。
   trailing: new Icon(
     alreadySaved?Icons.favorite:Icons.favorite_border,
     color: alreadySaved?Colors.red:null,
   ),
//      為心形增加點選方法
     onTap: (){
      setState((){//在 Flutter 的響應式風格的框架中,呼叫 setState() 會為 State 物件觸發 build() 方法,從而導致對 UI 的更新
        if(alreadySaved){
          _saved.remove(pair);
        }else{
          _saved.add(pair);
        }
      });
     },
   );

 }

我們成功的給心形圖片新增的點選切換效果,熱過載之後如下圖所示:

這裡寫圖片描述

導航到新頁面(Flutter的路由)

在這一步中,我們將新增一個顯示收藏夾內容的新頁面(在 Flutter 中稱為路由[route])。我們將您將在主路由和新路由之間導航(切換頁面)。

在 Flutter 中,導航器管理應用程式的路由棧。將路由推入(push)到導航器的棧中,將會顯示更新為該路由頁面。 從導航器的棧中彈出(pop)路由,將顯示返回到前一個路由。

我們在 RandomWordsState 的build方法中為 AppBar 新增一個列表圖示。當用戶點選列表圖示時,包含收藏夾的新路由頁面入棧顯示。

將該圖示及其相應的操作新增到build方法中:

class RandomWordsState extends State<RandomWords> {
//  在 Dart 語言中使用下劃線字首識別符號,會強制其變成私有。
  final List<WordPair> _suggetions = <WordPair>[];
  final TextStyle _biggerFont = const TextStyle(fontSize: 18.0);
//   新增一個 _saved Set(集合),儲存使用者喜歡(收藏)的單詞對。不要用 List ,因為 Set 中不允許重複的值。
  final Set<WordPair> _saved=new Set<WordPair>();
 @override
 Widget build(BuildContext context) {
   // 使用 Scaffold 類實現基礎的 Material Design 佈局
   return new Scaffold(
     appBar: new AppBar(
       title: const Text('Flutter APP Demo'),
//         build 方法中為 AppBar 新增一個列表圖示。當用戶點選列表圖示時,包含收藏夾的新路由頁面入棧顯示。
         actions: <Widget>[
           //某些 widget 屬性需要單個 widget(child),而其它一些屬性,如 action,需要一組widgets(children),用方括號 [] 表示。
           new IconButton(icon: const Icon(Icons.list), onPressed: _pushSaved),
         ],

         ),
     body: _buildSuggestions(),
   );

 }

在RandomWordsState這個類裡新增_pushSaved()方法《綠色部分》:

class RandomWordsState extends State<RandomWords> {
 ...

 void _pushSaved() {
 }

}

熱過載應用,列表圖示將會出現在導航欄中。現在點選它不會有任何反應,因為_pushSaved函式還是空的。

接下來,(當用戶點選導航欄中的列表圖示時)我們會建立一個路由並將其推入到導航管理器棧中。此操作會切換頁面以顯示新路由,新頁面的內容會在 MaterialPageRoute 的builder屬性中構建,builder是一個匿名函式。

  • 新增Navigator.push呼叫,這會使路由入棧(以後路由入棧均指推入到導航管理器的棧)
void _pushSaved() {
 Navigator.of(context).push(
 );
}

接下來,新增 MaterialPageRoute 及其 builder。 現在,新增生成 ListTile 行的程式碼,ListTile 的divideTiles()方法在每個 ListTile 之間新增 1 畫素的分割線。 該divided變數持有最終的列表項,並通過toList()方法非常方便的轉換成列表顯示。

-新增 MaterialPageRoute 及其 builder

void _pushSaved() {
//     新增 Navigator.push 呼叫,這會使路由入棧(本系列路由入棧均指推入到導航管理器的棧)
     Navigator.of(context).push(
//        新增 MaterialPageRoute 及其 builder
       new MaterialPageRoute<void>(
           builder: (BuildContext context){
             final Iterable<ListTile> tiles=_saved.map(
                 (WordPair pair){
                   return new ListTile(
                     title: new Text(
                       pair.asPascalCase,
                       style: _biggerFont,
                     ),
                   );
                 }
             );
             final List<Widget> divided=ListTile
             .divideTiles(
                 context: context,
                 tiles: tiles,)
             .toList();

           })

     );
 }

新增水平分隔符

void _pushSaved() {
//     新增 Navigator.push 呼叫,這會使路由入棧(本系列路由入棧均指推入到導航管理器的棧)
     Navigator.of(context).push(
//        新增 MaterialPageRoute 及其 builder
       new MaterialPageRoute<void>(
           builder: (BuildContext context){
             final Iterable<ListTile> tiles=_saved.map(
                 (WordPair pair){
                   return new ListTile(
                     title: new Text(
                       pair.asPascalCase,
                       style: _biggerFont,
                     ),
                   );
                 }
             );
             final List<Widget> divided=ListTile
             .divideTiles(
                 context: context,
                 tiles: tiles,)
             .toList();
//              新增水平分隔符,
           return new Scaffold(
             appBar: new AppBar(
               title: const Text('Saved Suggestions'),
             ),
             body: new ListView(
               children: divided,
             ),
           );

           })

     );
 }

熱過載應用程式,點選列表項收藏一些項,點選列表圖示,在新的 route(路由)頁面中顯示收藏的內容。Navigator(導航器)會在應用欄中自動新增一個”返回”按鈕,無需呼叫Navigator.pop,點選後退按鈕就會返回到主頁路由。

效果圖如下:
這裡寫圖片描述

使用 Themes 修改 UI

  • Flutter 裡我們使用theme來控制你應用的外觀和風格,你可以使用預設主題,該主題取決於物理裝置或模擬器,也可以自定義主題以適應您的品牌
  • 可以通過配置ThemeData類輕鬆更改應用程式的主題,目前我們的應用程式使用預設主題,下面將更改 primaryColor 顏色為粉色。

在 MyApp 這個類裡修改顏色:

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return new MaterialApp(
     title: 'Flutter 下的List列表',
//      通過配置 ThemeData 類輕鬆更改應用程式的主題
     theme: new ThemeData(
       primaryColor: Colors.deepOrangeAccent,
     ),
     home: new RandomWords(),

   );
 }
}

熱過載應用。 你會發現,整個背景將會變為粉色,包括 app bar(應用欄)
這裡寫圖片描述