我有以下 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();
},);
}),
]
)
)
]));
}
}
答案 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, _) {
});