在Flutter中将数据从一页传递到另一页 [英] Pass data from one page to another in Flutter

查看:73
本文介绍了在Flutter中将数据从一页传递到另一页的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道有很多这样的问题,但是我是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.

我基本上有 settings.dart home.dart 。现在,我要根据米 _isMetresChecked 或英尺 _isFeetChecked 的复选框值进行操作,更改主屏幕上的设备,但不要立即切换到主屏幕,允许用户继续配置设置(最终会有更多添加),并且当他们返回主屏幕时,它将更新。我尝试使用类 SettingsData 来合并所有配置,然后通过 Navigator 传递它,但是尽管事实上,我没有成功,它不会让我让用户停留在设置页面上。

I basically have settings.dart and home.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. 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.

那么如何在视图之间传递数据而又不切换视图?

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

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,
            ),

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


推荐答案

所以首先,您只需要1 bool即可进行测量。英尺或米。这样可以简化事情。这是一个使用回调函数在父窗口小部件中设置状态更改的示例。这只是许多可以完成的方式中的一种,可能还有其他您可能更喜欢的方式。

So first of all you only need 1 bool for your measurements. 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),
          ),
        ],
      ),
    );
  }
}

这篇关于在Flutter中将数据从一页传递到另一页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆