简体   繁体   English

在 Flutter 中将数据从一个页面传递到另一个页面

[英]Pass data from one page to another in Flutter

I know there are a ton of questions like these but I'm brand new to Flutter and I haven't found a post that suits my needs or maybe I'm just thinking about it wrong.我知道有很多这样的问题,但我是 Flutter 的新手,我还没有找到适合我需求的帖子,或者我只是想错了。

I basically have settings.dart and home.dart .我基本上有settings.darthome.dart Right now, what I'd like to do is based on the checkbox value for either metres _isMetresChecked or feet _isFeetChecked , change the unit on the home screen but don't immediately switch to the home screen, allow the user to continue configuring settings (there are more to add in eventually) and when they go back to the homescreen, it updates.现在,我想做的是基于米_isMetresChecked或英尺_isFeetChecked的复选框值,更改主屏幕上的单位,但不要立即切换到主屏幕,允许用户继续配置设置(最终还有更多内容要添加),当他们返回主屏幕时,它会更新。 I tried to use the class SettingsData as a way to merge all the configurations and then pass it via Navigator but despite the fact that I was unsuccessful, it wouldn't have let me allow the user to stay on the 'Settings' page.我尝试使用类SettingsData作为合并所有配置的一种方式,然后通过Navigator传递它,但尽管我没有成功,但它不会让我允许用户停留在“设置”页面上。

So how can I pass data between views, without switching views?那么如何在不切换视图的情况下在视图之间传递数据呢?

home.dart家.dart

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

import 'applicationbar.dart';
import 'navigationdrawer.dart';
import 'bluetooth.dart';


class LuggageFollowerMain extends StatefulWidget {
  @override
  _LuggageFollowerMainState createState() => _LuggageFollowerMainState();
}

class _LuggageFollowerMainState extends State<LuggageFollowerMain> {
  String _string = '0m';  //so if _isFeetChecked is true in settings.dart this is '0ft'


  @override
  Widget build(BuildContext context) {

    return Scaffold(
      backgroundColor: Colors.grey[900],
      appBar: ApplicationBar(title: 'Luggage Follower'),
      drawer: NavigationDrawer(),
      body:Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0),
            child: Text('Luggage Status', style: Theme.of(context).textTheme.body2),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0),
            child: Text('Paired', style: Theme.of(context).textTheme.body1),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 20,horizontal: 0),
            child: Divider(height: 3.0, color: Colors.pinkAccent, indent: 150, endIndent: 150),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0),
            child: Text('Distance to Luggage', style: Theme.of(context).textTheme.body2),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0),
            child: Text(_string, style: Theme.of(context).textTheme.body1), //dynamic text here
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0),
            child: LuggageFollow(),
          ),
        ],
      ),
    );
  }
}

settings.dart设置.dart

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

import 'applicationbar.dart';
import 'navigationdrawer.dart';

class SettingsData {
  bool feet;
  bool metres;

  SettingsData({this.feet, this.metres});
}

class Settings extends StatefulWidget {
  @override
  _SettingsState createState() => _SettingsState();
}

class _SettingsState extends State<Settings> {
  static bool _isFeetChecked   = false;
  static bool _isMetersChecked = true;


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: ApplicationBar(title: 'Settings'),
      drawer: NavigationDrawer(),
      body: Column(
          //crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Padding(
              padding: EdgeInsets.symmetric(vertical: 20.0,horizontal: 20),
              child: Text('Distance Units')
            ),
            Divider(
              height: 3.0,
              color: Colors.pink,
            ),
            Padding(
              padding: EdgeInsets.symmetric(vertical: 20.0,horizontal: 0),
              child: CheckboxListTile(
                title: Text('Distance in feet', style: Theme.of(context).textTheme.body1),
                value: _isFeetChecked,
                onChanged: (bool value) {
                  setState(() {
                    _isFeetChecked = value; _isMetersChecked = !value;});
                },
                checkColor: Colors.white,
                activeColor: Colors.pink,
                subtitle: Text('1 foot ~ 0.3 metres',style: Theme.of(context).textTheme.display2),
              ),
            ),
            Padding(
              padding: EdgeInsets.symmetric(vertical: 20.0,horizontal: 0),
              child: CheckboxListTile(
                title: Text('Distance in metres', style: Theme.of(context).textTheme.body1),
                value: _isMetersChecked,
                onChanged: (bool value) {
                  setState(() { _isMetersChecked = value; _isFeetChecked = !value;updateData();});
                },
                checkColor: Colors.white,
                activeColor: Colors.pink,
                subtitle: Text('1 metre ~ 3 feet',style: Theme.of(context).textTheme.display2),
              ),
            ),
            Padding(
              padding: EdgeInsets.symmetric(vertical: 30.0,horizontal: 20),
              child: Text('Notifications')
            ),
            Divider(
                height: 3.0,
                color: Colors.pink,
            ),

              ),
            ),
          ],
      ),
    );
  }
}

I know there are a ton of questions like these but I'm brand new to Flutter and I haven't found a post that suits my needs or maybe I'm just thinking about it wrong.我知道有很多这样的问题,但是我对Flutter还是陌生的,我还没有找到适合我需求的帖子,或者我只是在想错了。

I basically have settings.dart and home.dart .我基本上有settings.darthome.dart Right now, what I'd like to do is based on the checkbox value for either metres _isMetresChecked or feet _isFeetChecked , change the unit on the home screen but don't immediately switch to the home screen, allow the user to continue configuring settings (there are more to add in eventually) and when they go back to the homescreen, it updates.现在,我要基于米_isMetresChecked或英尺_isFeetChecked的复选框值,在主屏幕上更改单位,但不要立即切换到主屏幕,允许用户继续配置设置(最终还有更多内容要添加),然后当他们返回主屏幕时,它就会更新。 I tried to use the class SettingsData as a way to merge all the configurations and then pass it via Navigator but despite the fact that I was unsuccessful, it wouldn't have let me allow the user to stay on the 'Settings' page.我尝试使用SettingsData类作为合并所有配置,然后通过Navigator传递它的一种方法,但是尽管我没有成功,但不允许我让用户停留在“ Settings”页面上。

So how can I pass data between views, without switching views?那么,如何在视图之间传递数据而又不切换视图?

home.dart飞镖

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

import 'applicationbar.dart';
import 'navigationdrawer.dart';
import 'bluetooth.dart';


class LuggageFollowerMain extends StatefulWidget {
  @override
  _LuggageFollowerMainState createState() => _LuggageFollowerMainState();
}

class _LuggageFollowerMainState extends State<LuggageFollowerMain> {
  String _string = '0m';  //so if _isFeetChecked is true in settings.dart this is '0ft'


  @override
  Widget build(BuildContext context) {

    return Scaffold(
      backgroundColor: Colors.grey[900],
      appBar: ApplicationBar(title: 'Luggage Follower'),
      drawer: NavigationDrawer(),
      body:Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0),
            child: Text('Luggage Status', style: Theme.of(context).textTheme.body2),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0),
            child: Text('Paired', style: Theme.of(context).textTheme.body1),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 20,horizontal: 0),
            child: Divider(height: 3.0, color: Colors.pinkAccent, indent: 150, endIndent: 150),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0),
            child: Text('Distance to Luggage', style: Theme.of(context).textTheme.body2),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0),
            child: Text(_string, style: Theme.of(context).textTheme.body1), //dynamic text here
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10,horizontal: 0),
            child: LuggageFollow(),
          ),
        ],
      ),
    );
  }
}

settings.dart settings.dart

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

import 'applicationbar.dart';
import 'navigationdrawer.dart';

class SettingsData {
  bool feet;
  bool metres;

  SettingsData({this.feet, this.metres});
}

class Settings extends StatefulWidget {
  @override
  _SettingsState createState() => _SettingsState();
}

class _SettingsState extends State<Settings> {
  static bool _isFeetChecked   = false;
  static bool _isMetersChecked = true;


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: ApplicationBar(title: 'Settings'),
      drawer: NavigationDrawer(),
      body: Column(
          //crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Padding(
              padding: EdgeInsets.symmetric(vertical: 20.0,horizontal: 20),
              child: Text('Distance Units')
            ),
            Divider(
              height: 3.0,
              color: Colors.pink,
            ),
            Padding(
              padding: EdgeInsets.symmetric(vertical: 20.0,horizontal: 0),
              child: CheckboxListTile(
                title: Text('Distance in feet', style: Theme.of(context).textTheme.body1),
                value: _isFeetChecked,
                onChanged: (bool value) {
                  setState(() {
                    _isFeetChecked = value; _isMetersChecked = !value;});
                },
                checkColor: Colors.white,
                activeColor: Colors.pink,
                subtitle: Text('1 foot ~ 0.3 metres',style: Theme.of(context).textTheme.display2),
              ),
            ),
            Padding(
              padding: EdgeInsets.symmetric(vertical: 20.0,horizontal: 0),
              child: CheckboxListTile(
                title: Text('Distance in metres', style: Theme.of(context).textTheme.body1),
                value: _isMetersChecked,
                onChanged: (bool value) {
                  setState(() { _isMetersChecked = value; _isFeetChecked = !value;updateData();});
                },
                checkColor: Colors.white,
                activeColor: Colors.pink,
                subtitle: Text('1 metre ~ 3 feet',style: Theme.of(context).textTheme.display2),
              ),
            ),
            Padding(
              padding: EdgeInsets.symmetric(vertical: 30.0,horizontal: 20),
              child: Text('Notifications')
            ),
            Divider(
                height: 3.0,
                color: Colors.pink,
            ),

              ),
            ),
          ],
      ),
    );
  }
}

So first of all you only need 1 bool for your measurements.因此,首先您只需要 1 个布尔值即可进行测量。 It's either feet or meters.它要么是英尺,要么是米。 So that simplifies things a bit.所以这简化了一些事情。 Here is a example using a callback function to set the state change in the parent widget.这是一个使用回调函数设置父小部件中状态更改的示例。 This is just one way of many this can be done and there may be other ways you may like better.这只是可以完成的许多方法中的一种,可能还有其他您可能更喜欢的方法。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: LuggageFollowerMain(),
    );
  }
}


class Settings extends StatefulWidget {

  //Static references to our parent widget varibles
  final bool isM;
  final changeMeeters;

  Settings(bool isM, changeMeeters(bool meeters)):
  this.isM = isM,
  this.changeMeeters = changeMeeters
  ;

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

class _SettingsState extends State<Settings> {
  @override
  void initState() { 
    super.initState();
    //set our varible state to be that of the parent screen
    //isMeeters is a local var to Settings and is changeable. 
    //isM is a static and can't be changed. isM was passed in 
    //from our home screen. We need a changeable var or the 
    //checkboxes won't update correctly. Thats why we need 
    //isMeeters (lol bad spelling). When the settings screen 
    //first loads we use initState to take the value of 
    //isM(from our home screen) and copy it into isMeeters 
    //as it's initial value before it is built and shown 
    //to the user for the first time. 
    isMeeters = widget.isM;
  }

  //our varible to use for our check boxes
  var isMeeters;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: <Widget>[
          Padding(
              padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 20),
              child: Text('Distance Units')),
          Divider(
            height: 3.0,
            color: Colors.pink,
          ),
          Padding(
            padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 0),
            child: CheckboxListTile(
              title: Text('Distance in feet',
                  style: Theme.of(context).textTheme.body1),
              //use the local var change when tapped
              value: isMeeters,
              onChanged: (bool value) {
                setState(() {
                  isMeeters = true;
                });
                //call back to the parent widget so it can be updated
                widget.changeMeeters(true);
              },
              checkColor: Colors.white,
              activeColor: Colors.pink,
              subtitle: Text('1 foot ~ 0.3 metres',
                  style: Theme.of(context).textTheme.display2),
            ),
          ),
          Padding(
            padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 0),
            child: CheckboxListTile(
              title: Text('Distance in metres',
                  style: Theme.of(context).textTheme.body1),
              //use the local var change when tapped. Use ! to invert the bool. This way only one is needed.
              value: !isMeeters,
              onChanged: (bool value) {
                setState(() {
                  isMeeters = false;
                });
                //call back to the parent widget so it can be updated
                widget.changeMeeters(false);
              },
              checkColor: Colors.white,
              activeColor: Colors.pink,
              subtitle: Text('1 metre ~ 3 feet',
                  style: Theme.of(context).textTheme.display2),
            ),
          ),
          Padding(
              padding: EdgeInsets.symmetric(vertical: 30.0, horizontal: 20),
              child: Text('Notifications')),
          Divider(
            height: 3.0,
            color: Colors.pink,
          ),
        ],
      ),
    );
  }
}

class LuggageFollowerMain extends StatefulWidget {
  @override
  _LuggageFollowerMainState createState() => _LuggageFollowerMainState();
}

class _LuggageFollowerMainState extends State<LuggageFollowerMain> {
      //store the distance as a number not a string
      double distance = 0.0;
      //store the measurement type setting
      bool isMeeters = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => Settings(isMeeters, (newMeeters){
              //when we get our callback from settings we set the change to the home screen var here
              setState(() {
                isMeeters = newMeeters;
              });

            })),
          );
        },
      ),
      backgroundColor: Colors.grey[900],
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0),
            child: Text('Luggage Status',
                style: Theme.of(context).textTheme.body2),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0),
            child: Text('Paired', style: Theme.of(context).textTheme.body1),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 0),
            child: Divider(
                height: 3.0,
                color: Colors.pinkAccent,
                indent: 150,
                endIndent: 150),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0),
            child: Text('Distance to Luggage',
                style: Theme.of(context).textTheme.body2),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0),
            //use the new number var and change it's suffix m or f depending on what our setting is.
            child: Text(distance.toString() + (isMeeters ? "m" : "f"),
                style: Theme.of(context).textTheme.body1), //dynamic text here
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 0),
          ),
        ],
      ),
    );
  }
}

To pass data from one page to another, you can make use of passing arguments to a named route .要将数据从一个页面传递到另一个页面,您可以使用向命名路由传递参数

Below is a minimal example of passing a boolean to and from the Settings page by way of arguments.下面是通过参数的方式在设置页面之间传递布尔值的最小示例。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
      routes: {
        "home": (BuildContext homeContext) => HomePage(),
        "settings": (BuildContext settingsContext) => SettingsPage(),
      },
      initialRoute: "home",
    );
  }
}

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

class _HomePageState extends State<HomePage> {
  bool _isMetersAccordingToHomePage = false;

  void _updateIsMetersAccordingToHomePage(bool _value) {
    setState(() {
      _isMetersAccordingToHomePage = _value ?? _isMetersAccordingToHomePage;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Home Page")),
      body: Column(
        children: <Widget>[
          Text("Is Displayed in meters? $_isMetersAccordingToHomePage"),
          RaisedButton(
            onPressed: () {
              // This is the important part
              Navigator.of(context)
                  .pushNamed(
                "settings",
                // we are passing a value to the settings page
                arguments: _isMetersAccordingToHomePage,
              )
                  // and then, when we `pop` from the settings page,
                  // we will get back an updated value
                  .then(
                (_isMetersAccordingToSettingsPage) {
                  _updateIsMetersAccordingToHomePage(
                      _isMetersAccordingToSettingsPage);
                },
              );
            },
            child: Text("Go to Settings Page"),
          ),
        ],
      ),
    );
  }
}

class SettingsPage extends StatefulWidget {
  @override
  _SettingsPageState createState() => _SettingsPageState();
}

class _SettingsPageState extends State<SettingsPage> {
  bool _isMetersAccordingToSettingsPage;

  void _updateIsMetersAccordingToSettingsPage(bool _value) {
    setState(() {
      _isMetersAccordingToSettingsPage = _value;
    });
  }

  @override
  Widget build(BuildContext context) {
    bool _isMetersAccordingToHomePage =
        ModalRoute.of(context).settings.arguments;

    return Scaffold(
      appBar: AppBar(
        title: Text("Setting Page"),
        leading: IconButton(
          icon: Icon(Icons.arrow_back_ios),
          onPressed: () {
            Navigator.of(context).pop<bool>(_isMetersAccordingToSettingsPage);
          },
        ),
      ),
      body: Column(
        children: <Widget>[
          CheckboxListTile(
            value: _isMetersAccordingToSettingsPage ??
                _isMetersAccordingToHomePage ??
                false,
            onChanged: _updateIsMetersAccordingToSettingsPage,
            title: Text("Display in meters?"),
          ),
        ],
      ),
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 flutter dart 中将图像选择器文件从一页传递到另一页? - How to pass image picker file from one page to another in flutter dart? 我想在颤振中将数据从一个屏幕传递到另一个屏幕并将数据保存到 ListView/ListTiles - I want to pass data from one screen to another screen in flutter and save the data to ListView/ListTiles 从一页转换到另一页 - Flutter - Transitioning from one page to another - Flutter 将变量从页面传递到另一个页面。 颤振/飞镖 - Pass variables from page to another page. Flutter/Dart 如何使用 PageRouteBuilder 将数据从一个 class 传递到 flutter 中的另一个 class - How to pass data from one class to another class in flutter using PageRouteBuilder 我想在flutter中将数据发送到一页并显示另一页 - I Want to send data to one page and display another page in flutter 将数据从一个活动传递到另一个活动并保存 - pass data from one activity to another and save it 将数据从一个片段传递到另一个-SharedPreferences - Pass data from one Fragment to another - SharedPreferences 如何将数据从一个片段传递到另一个片段 - How Pass data from one fragment to another Flutter:如何在没有 Navigator 的情况下将值从一个文件传递到另一个文件? - Flutter: how to pass values from one file to another without Navigator?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM