在不相关的两个不相关屏幕之间传递数据

时间:2020-09-16 18:49:48

标签: flutter

我有以下 FiltersScreen ,其中包含2个过滤器和一个保存按钮。当用户切换过滤器并单击“保存”按钮时,我想将这些值传递给 CategoryMealsScreen 。如何传递这些值?这两个屏幕之间没有导航,所以我不能使用push或pushNamed路由。

这是两个类:

class FiltersScreen extends StatefulWidget {
  @override
  _FilterScreenState createState() => _FilterScreenState();
}

class _FilterScreenState extends State<FiltersScreen> {
  var _glutenFree = false;  
   var _lactoseFree = false; 

  Widget _buildSwitchListTile(String title, String subTitle, bool currentValue, Function updateValue){ 
       return  SwitchListTile(title:Text(title), 
                    value:currentValue, 
                    subtitle: Text(subTitle),
                    onChanged: updateValue
                    );
  }

  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('Filter'), 
        actions:<Widget>[
          IconButton(icon:Icon(Icons.save), onPressed: () {  },),
        ],
        ),
        
        drawer: MainDrawer(),
        body:  Column(children:<Widget>[
          Container(
            padding: EdgeInsets.all(20),
            child:Text('Adjust your meal selection', 
            style:Theme.of(context).textTheme.title), ), 
            Expanded(
              child:ListView(
                children:<Widget>[
                  _buildSwitchListTile('Gluten-free',
                  'Only include gluten free meals',
                   _glutenFree, 
                  (newValue){setState((){ 
                      _glutenFree = newValue; 
                   },); 
                  }),
                  _buildSwitchListTile('Lactose',
                  'Only include lactose free meals',
                   _lactoseFree, 
                  (newValue){setState((){ 
                      _lactoseFree = newValue; 
                   },);  
                  })]
              )
            )
        ]));
  }
}

以下是应该接收值的类:

    class CategoryMealsScreen extends StatefulWidget {
  final String categoryId;
  final String categoryTitle;

  CategoryMealsScreen(this.categoryId, this.categoryTitle);

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

class _CategoryMealsScreenState extends State<CategoryMealsScreen> {
  @override
  Widget build(BuildContext context) {
    final categoryMeals = DUMMY_MEALS.where((meal) {
      return meal.categories.contains(widget.categoryId);
    }).toList();
    return Scaffold(
      appBar: AppBar(title: Text(widget.categoryTitle)),
     body: ListView.builder(
        itemBuilder: (ctx, index) {
          return MealItem(
            id:categoryMeals[index].id,
            title: categoryMeals[index].title,
            imageUrl: categoryMeals[index].imageUrl,
            duration: categoryMeals[index].duration,
            affordability: categoryMeals[index].affordability,
            complexity: categoryMeals[index].complexity,
          );
        },
        itemCount: categoryMeals.length,
      ),
    );
  }
}

已编辑

CategoryMealsScreen中,如何同时使用_glutenFree_lactoseFree值?

这是我更新的代码:

类别用餐屏幕

 class CategoryMealsScreen extends StatefulWidget {
  final String categoryId;
  final String categoryTitle;

  CategoryMealsScreen(this.categoryId, this.categoryTitle);

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

    class _CategoryMealsScreenState extends State<CategoryMealsScreen> {
      @override
      Widget build(BuildContext context) {
        ValueListenable<bool> _glutenFree;
        ValueListenable<bool> _lactoseFree;
    
        return ValueListenableBuilder(
            valueListenable: _glutenFree,
            builder: (context, value, _) {
              final categoryMeals = DUMMY_MEALS.where((meal) {
                if (_glutenFree.value && !meal.isGlutenFree) {
                  return false;
                }
                if (_lactoseFree.value && !meal.isLactoseFree) {
                  return false;
                }
                return true;
              }).toList();
    
              //Every independent screen must have a scaffold
              return Scaffold(
                appBar: AppBar(title: Text(widget.categoryTitle)),
                body: ListView.builder(
                  itemBuilder: (ctx, index) {
                    return MealItem(
                      id: categoryMeals[index].id,
                      title: categoryMeals[index].title,
                      imageUrl: categoryMeals[index].imageUrl,
                      duration: categoryMeals[index].duration,
                      affordability: categoryMeals[index].affordability,
                      complexity: categoryMeals[index].complexity,
                    );
                  },
                  itemCount: categoryMeals.length,
                ),
              );
            });
      }
    }

FiltersScreen

class FiltersScreen extends StatefulWidget {
  @override
  _FilterScreenState createState() => _FilterScreenState();
}

class _FilterScreenState extends State<FiltersScreen> {

ValueNotifier<bool> _glutenFree = new ValueNotifier(false);
ValueNotifier<bool> _lactoseFree = new ValueNotifier(false);

  Widget _buildSwitchListTile(String title, String subTitle, ValueNotifier<bool> currentValue, Function updateValue){ 
       return  SwitchListTile(title:Text(title), 
                    value:currentValue.value, 
                    subtitle: Text(subTitle),
                    onChanged: updateValue
                    );
  }

  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('Filter'), 
        actions:<Widget>[
          IconButton(icon:Icon(Icons.save), onPressed: () {  },),
        ],
        ),
        
        drawer: MainDrawer(),
        body:  Column(children:<Widget>[
          Container(
            padding: EdgeInsets.all(20),
            child:Text('Adjust your meal selection', 
            style:Theme.of(context).textTheme.title), ), 
            Expanded(
              child:ListView(
                children:<Widget>[
                  _buildSwitchListTile('Gluten-free',
                  'Only include gluten free meals',
                   _glutenFree, 
                  (newValue){setState((){ 
                      _glutenFree.value = newValue; //setting the value
                     _glutenFree.notifyListeners(); //all the widget who is listening to this value, let them know the change
                   },); 
                  }),
                  _buildSwitchListTile('Lactose',
                  'Only include lactose free meals',
                   _lactoseFree, 
                  (newValue){setState((){ 
                      _lactoseFree = newValue; 
                      _lactoseFree.notifyListeners(); 
                   },); 
                  }),
                  ]
              )
            )
        ]));
  }
}

1 个答案:

答案 0 :(得分:2)

您可以通过使用ValueNotifier来保存过滤器类的更改,并在Category类中使用ValueListenableBuilder来监听该值更改并在其中进行必要的更改,从而达到这种过滤效果。用户界面。

让我们跳到解决方案中,在您的FiltersScreen中,替换此代码

var _glutenFree = false;
var _lactoseFree = false;

具有ValueNotifier种对象。所以看起来像这样

ValueNotifier<bool> _glutenFree = new ValueNotifier(false);
ValueNotifier<bool> _lactoseFree = new ValueNotifier(false);

更改点击值也非常相似。所以这个

setState((){
    _glutenFree = newValue; 
 });

将更改为此

setState((){
    _glutenFree.value = newValue; //setting the value
    _glutenFree.notifyListeners(); //all the widget who is listening to this value, let them know the change
 });

现在,最后一步,设置一个小部件构建器,以侦听此值更改并在树中重新构建所有小部件。

为此,只需将其作为小部件添加到CategoryMealsScreen

ValueListenableBuilder(
    valueListenable: _glutenFree,
    builder: (context, value, _) {
});