Skip to content

[Flutter] 頁面跳轉時傳遞參數、接收參數

Last Updated on 2021-05-12 by Clay

在我們設計一款 App 的時候,很難在同一個頁面把所有的功能做完。大多數時候,我們需要依照不同的功能,來讓使用者跳轉到不同的頁面。

比方說使用者正在主要的頁面玩遊戲,突然需要改動一些畫面的設定,那麼我們就可以設計一個按鈕,只要使用者按下按鈕,就可以跳轉到專門設定的頁面。

本篇文章主要紀錄在 Flutter 中,頁面跳轉時該如何傳遞參數、接受參數。主要分成以下三小節。

  • 傳遞參數給 StatelessWidget
  • 傳遞參數給 StatefulWidget
  • 當頁面返回時接受回傳的參數

傳遞參數給 StatelessWidget

以下是段簡短的範例程式碼。架構相當簡單,第一頁(HomePage)只有一個輸入框跟一個按鈕,按下按鈕後,輸入框內的文字會被傳送到第二個頁面(SecondPage)。

而第二個頁面則簡單地顯示接收到的參數(第一頁輸入的文字)。

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';


void main() => runApp(MyApp());


// MyApp
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

// HomePage
class HomePage extends StatelessWidget {
  // TextEditingController
  TextEditingController _dataController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Home Page"),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            TextField(
              autofocus: true,
              decoration: InputDecoration(
                labelText: "data:",
                hintText: "data will display on the second page",
                prefixIcon: Icon(Icons.font_download),
              ),
              obscureText: false,
              controller: _dataController,
            ),
            ElevatedButton(
              child: Text("Jump to second page"),
              onPressed: () {
                Navigator.push(
                    context,
                    MaterialPageRoute(
                        builder: (context) => SecondPage(
                          data: _dataController.text,
                        )
                    )
                );
              },
            ),
          ],
        )
      ),
    );
  }
}

// SecondPage
class SecondPage extends StatelessWidget {
  SecondPage({Key? key, required this.data}) : super(key: key);
  final String data;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Page"),
      ),
      body: Column(
        children: <Widget>[
          Text("the data is: $data"),
        ],
      ),
    );
  }
}



Output:

https://clay-atlas.com/wp-content/uploads/2021/05/Screen-Recording-2021-05-11-at-7.39.35-PM.mov

傳遞參數給 StatefulWidget

StatefulWidget 跟 StatelessWidget 的傳遞方法又有一點點微妙的不同。

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';


void main() => runApp(MyApp());


// MyApp
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

// HomePage
class HomePage extends StatelessWidget {
  // TextEditingController
  TextEditingController _dataController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Home Page"),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            TextField(
              autofocus: true,
              decoration: InputDecoration(
                labelText: "data:",
                hintText: "data will display on the second page",
                prefixIcon: Icon(Icons.font_download),
              ),
              obscureText: false,
              controller: _dataController,
            ),
            ElevatedButton(
              child: Text("Jump to second page"),
              onPressed: () {
                Navigator.push(
                    context,
                    MaterialPageRoute(
                        builder: (context) => SecondPage(
                          data: _dataController.text,
                        )
                    )
                );
              },
            ),
          ],
        )
      ),
    );
  }
}

// SecondPage
class SecondPage extends StatefulWidget {
  SecondPage({Key? key, required this.data}) : super(key: key);
  final String data;

  @override
  _SecondPageState createState() => _SecondPageState();
}

// _SecondPageState
class _SecondPageState extends State<SecondPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Page"),
      ),
      body: Column(
        children: <Widget>[
          Text("the data is: ${widget.data}"),
        ],
      ),
    );
  }
}




Output:

https://clay-atlas.com/wp-content/uploads/2021/05/Screen-Recording-2021-05-11-at-7.56.54-PM.mov

其實展示效果跟前一節很像;為了證明我不是拿同個影片來放,我將 today 改成了 nice。


當頁面返回時接受回傳的參數

接受回傳的參數比較麻煩一點,我們需要另外寫異步參數,等待第二個頁面參數的回傳、並在確實取得參數後,再來更新原先的 HomePage 頁面狀態。

另外,若要回傳參數,我們也需要在 SecondPageState 的部分另外撰寫按鈕,使用 Navigator.pop(context, data); 返回我們想要的 data 參數。

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';


void main() => runApp(MyApp());


// MyApp
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

// HomePage
class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}


// HomePage
class _HomePageState extends State<HomePage> {
  // TextEditingController
  TextEditingController _dataController = TextEditingController();
  var returnTextContent = "";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Home Page"),
      ),
      body: Center(
          child: Column(
            children: <Widget>[
              TextField(
                autofocus: true,
                decoration: InputDecoration(
                  labelText: "data:",
                  hintText: "data will display on the second page",
                  prefixIcon: Icon(Icons.font_download),
                ),
                obscureText: false,
                controller: _dataController,
              ),
              ElevatedButton(
                child: Text("Jump to second page"),
                onPressed: () {
                  _goSecondPage(context).then((value) {
                    setState(() {
                      returnTextContent = value;
                    });
                  });
                },
              ),
              SizedBox(
                height: 50.0,
              ),
              Text(
                returnTextContent.isNotEmpty ? returnTextContent : "No any return data",
              ),
            ],
          )
      ),
    );
  }

  // Go to the second page and receive the return value
  Future<String> _goSecondPage(BuildContext context) async {
    String returnText = await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => SecondPage(
          data: _dataController.text,
        ),
      ),
    );

    print("TEST OUTPUT");
    print(returnText);

    return returnText;
  }
}


// SecondPage
class SecondPage extends StatelessWidget {
  SecondPage({Key? key, required this.data}) : super(key: key);
  final String data;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Page"),
      ),
      body: Center(
        child:Column(
          children: <Widget>[
            Text("the data is: $data"),
            ElevatedButton(
              child: Text("Jump back the home page"),
              onPressed: () {
                Navigator.pop(context, data);
              },
            ),
          ],
        ),
      ),
    );
  }
}



Output:

https://clay-atlas.com/wp-content/uploads/2021/05/Screen-Recording-2021-05-11-at-9.36.09-PM.mov

References


Read More

Tags:

Leave a Reply取消回覆

Exit mobile version