I'm trying to develop a restaurant menu app and i need that when i click one of the text buttons bellow it filters the items according to which button i tap. when i built the "meal" object, i created an atribute called "idDiaSem", and i have 5 diferent id's that i need to display 5 diferent lists of itens based on the ID i choose. Here's the concept:
Here's a complete minimal-reproducible-example:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _idDiaSem = 'seg';
@override
Widget build(BuildContext context) {
final dayOfWeekMeals = meals
.where((meal) => meal.idDiaSem.any((idDiaSem) => idDiaSem == _idDiaSem))
.toList();
return Scaffold(
appBar: AppBar(
title: const Text('Gastronomia'),
),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: dayOfWeekMeals.length,
itemBuilder: (ctx, index) {
return Card(
elevation: 0,
margin: (index == dayOfWeekMeals.length - 1)
? const EdgeInsets.only(bottom: 0, left: 20, right: 20)
: const EdgeInsets.only(left: 20, right: 20),
child: ClipRRect(
borderRadius: (index == 0)
? const BorderRadius.only(
topLeft: Radius.circular(50),
topRight: Radius.circular(50),
)
: (index == dayOfWeekMeals.length - 1)
? const BorderRadius.only(
bottomLeft: Radius.circular(50),
bottomRight: Radius.circular(50),
)
: BorderRadius.circular(0),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(dayOfWeekMeals[index].descricao),
),
),
);
},
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SemanaButton(
'Segunda',
onPressed: () => setState(() => _idDiaSem = 'seg'),
selected: _idDiaSem == 'seg',
),
SemanaButton(
'Terça',
onPressed: () => setState(() => _idDiaSem = 'ter'),
selected: _idDiaSem == 'ter',
),
SemanaButton(
'Quarta',
onPressed: () => setState(() => _idDiaSem = 'qua'),
selected: _idDiaSem == 'qua',
),
SemanaButton(
'Quinta',
onPressed: () => setState(() => _idDiaSem = 'qui'),
selected: _idDiaSem == 'qui',
),
SemanaButton(
'Sexta',
onPressed: () => setState(() => _idDiaSem = 'sex'),
selected: _idDiaSem == 'sex',
),
],
),
],
),
);
}
}
class SemanaButton extends StatelessWidget {
final String text;
final bool? selected;
final VoidCallback onPressed;
const SemanaButton(
this.text, {
Key? key,
required this.onPressed,
this.selected,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onPressed,
child: Text(
'$text \n____________',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 11,
color:
selected == true ? Theme.of(context).colorScheme.primary : null,
fontWeight: selected == true ? FontWeight.bold : null,
),
),
);
}
}
class Meal {
final String id;
final String descricao;
final List<String> ingredients;
final List<String> idDiaSem;
final String imageUrl;
const Meal({
required this.id,
required this.descricao,
required this.ingredients,
required this.idDiaSem,
required this.imageUrl,
});
}
var id = 0;
final meals = [
Meal(
id: '${ id}',
descricao: 'Feijão Tropeiro',
ingredients: [],
idDiaSem: ['seg'],
imageUrl: '',
),
Meal(
id: '${ id}',
descricao: 'Feijoada',
ingredients: [],
idDiaSem: ['sex'],
imageUrl: '',
),
Meal(
id: '${ id}',
descricao: 'Batata Doce Caramelada',
ingredients: [],
idDiaSem: ['seg'],
imageUrl: '',
),
Meal(
id: '${ id}',
descricao: 'Cubos Suínos ao Molho Escuro',
ingredients: [],
idDiaSem: ['seg'],
imageUrl: '',
),
Meal(
id: '${ id}',
descricao: 'Enrolado de Salsicha',
ingredients: [],
idDiaSem: ['seg'],
imageUrl: '',
),
Meal(
id: '${ id}',
descricao: 'Doce e Fruta',
ingredients: [],
idDiaSem: ['seg', 'ter', 'qua', 'qui', 'sex'],
imageUrl: '',
),
Meal(
id: '${ id}',
descricao: 'Buffet de Saladas',
ingredients: [],
idDiaSem: ['seg', 'ter', 'qua', 'qui', 'sex'],
imageUrl: '',
),
];
CodePudding user response:
Well, here is the recipe for the required logic:
- Define a variable to contain the
id
that you would to filter the meals according to.
int _filterId;
- When any filter button is pressed, just set the value of the
_filterId
inside asetState()
block:
onTap: () {
setState(() => _filterId = 0); // Take care of the ID
},
- At the begining of the
build()
method, Define aList
ofMeal
that would contain the filtered meals in the future and set it to thedayOfWeekMeals
list if the_filterId
isnull
and apply the filter if it is notnull
, like the following:
List<Meal> _filteredMeals = _filterId == null ? dayOfWeekMeals : dayOfWeekMeals.where((meal) => meal.idDiaSem == _filterId).toList();
- Use the
_filteredMeals
list in theListView
instead ofdayOfWeekMeals
, for example:
itemCount: _filteredMeals.length,
MealItem(_filteredMeals[index])
NOTE: Don't forget to replace the others.
Side Note: You can start with an initial filter by just starting the variable _filterId
with an initial id of the filter.