1. ホーム
  2. dart

[解決済み] Flutterで画面間のデータを受け渡す

2023-04-12 16:15:41

質問

Flutterを勉強しているうちに、ナビゲーションにたどり着きました。画面間のデータ受け渡しは AndroidのActivity間のデータ受け渡し iOSにおけるビューコントローラー間のデータ受け渡し . Flutterではどうやるの?

関連する質問です。

どのように解決するのか?

この回答では、データを前方に渡すことと、データを後方に渡すことの両方を取り上げます。 AndroidのアクティビティやiOSのViewControllerとは異なり、Flutterの異なる画面は単なるウィジェットです。それらの間を移動するには、ルートと呼ばれるものを作成し、そのルートで Navigator を使ってスタックにルートをプッシュしたりポップしたりします。

次の画面へのデータの受け渡し

次の画面にデータを送るには、次のようなことをします。

  1. を作る。 SecondScreen のコンストラクタに、送信したいデータの種類を表すパラメータを渡すようにします。この例では、データは String の値であり、ここで this.text .

    class SecondScreen extends StatelessWidget {
      final String text;
      SecondScreen({Key key, @required this.text}) : super(key: key);
    
      ...
    
    
  2. 次に Navigator の中に FirstScreen ウィジェットにルートをプッシュするために SecondScreen ウィジェットに送信します。そのコンストラクタにパラメータとして送信したいデータを入れます。

    Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => SecondScreen(text: 'Hello',),
        ));
    
    

の完全なコードは main.dart はここにあります。

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: 'Flutter',
    home: FirstScreen(),
  ));
}

class FirstScreen extends StatefulWidget {
  @override
  _FirstScreenState createState() {
    return _FirstScreenState();
  }
}

class _FirstScreenState extends State<FirstScreen> {

  // this allows us to access the TextField text
  TextEditingController textFieldController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('First screen')),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [

          Padding(
            padding: const EdgeInsets.all(32.0),
            child: TextField(
              controller: textFieldController,
              style: TextStyle(
                fontSize: 24,
                color: Colors.black,
              ),
            ),
          ),

          RaisedButton(
            child: Text(
              'Go to second screen',
              style: TextStyle(fontSize: 24),
            ),
            onPressed: () {
              _sendDataToSecondScreen(context);
            },
          )

        ],
      ),
    );
  }

  // get the text in the TextField and start the Second Screen
  void _sendDataToSecondScreen(BuildContext context) {
    String textToSend = textFieldController.text;
    Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => SecondScreen(text: textToSend,),
        ));
  }
}

class SecondScreen extends StatelessWidget {
  final String text;

  // receive data from the FirstScreen as a parameter
  SecondScreen({Key key, @required this.text}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second screen')),
      body: Center(
        child: Text(
          text,
          style: TextStyle(fontSize: 24),
        ),
      ),
    );
  }
}

前画面へのデータの受け渡し

データを受け渡すときは、次のようなことが必要です。

  1. FirstScreen を使用します。 Navigator を押して(起動して)ください。 SecondScreenasync メソッドを呼び、それが終了したときに返す結果を待ちます。

    final result = await Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => SecondScreen(),
        ));
    
    
  2. には SecondScreen をポップする際にパラメータとして渡したいデータを記述します。 Navigator .

    Navigator.pop(context, 'Hello');
    
    
  3. 次に FirstScreenawait が終了し、その結果を使用することができます。

    setState(() {
      text = result;
    });
    
    

の完全なコードは次のとおりです。 main.dart の完全なコードを参考までに示します。

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: 'Flutter',
    home: FirstScreen(),
  ));
}

class FirstScreen extends StatefulWidget {
  @override
  _FirstScreenState createState() {
    return _FirstScreenState();
  }
}

class _FirstScreenState extends State<FirstScreen> {

  String text = 'Text';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('First screen')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [

            Padding(
              padding: const EdgeInsets.all(32.0),
              child: Text(
                text,
                style: TextStyle(fontSize: 24),
              ),
            ),

            RaisedButton(
              child: Text(
                'Go to second screen',
                style: TextStyle(fontSize: 24),
              ),
              onPressed: () {
                _awaitReturnValueFromSecondScreen(context);
              },
            )

          ],
        ),
      ),
    );
  }

  void _awaitReturnValueFromSecondScreen(BuildContext context) async {

    // start the SecondScreen and wait for it to finish with a result
    final result = await Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => SecondScreen(),
        ));

    // after the SecondScreen result comes back update the Text widget with it
    setState(() {
      text = result;
    });
  }
}

class SecondScreen extends StatefulWidget {
  @override
  _SecondScreenState createState() {
    return _SecondScreenState();
  }
}

class _SecondScreenState extends State<SecondScreen> {
  // this allows us to access the TextField text
  TextEditingController textFieldController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second screen')),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [

          Padding(
            padding: const EdgeInsets.all(32.0),
            child: TextField(
              controller: textFieldController,
              style: TextStyle(
                fontSize: 24,
                color: Colors.black,
              ),
            ),
          ),

          RaisedButton(
            child: Text(
              'Send text back',
              style: TextStyle(fontSize: 24),
            ),
            onPressed: () {
              _sendDataBack(context);
            },
          )

        ],
      ),
    );
  }

  // get the text in the TextField and send it back to the FirstScreen
  void _sendDataBack(BuildContext context) {
    String textToSendBack = textFieldController.text;
    Navigator.pop(context, textToSendBack);
  }
}