I created a card logic using ListView.separated
in Flutter. What I want to implement here is, the current date is implemented in gray. However, the issue lies in the logic for changing the card color only for the clicked dates.
This is my code:
Container date_card(BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height * 0.13,
width: MediaQuery.of(context).size.width * 1,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
// Today date
DateTime currentDate = DateTime.now();
DateTime startOfWeek =
currentDate.subtract(Duration(days: currentDate.weekday + 1));
DateTime itemDate = startOfWeek.add(Duration(days: index));
String formattedDate = DateFormat('d').format(itemDate);
String formattedDay = DateFormat('E').format(itemDate);
bool isToday =
formattedDate == DateFormat('d').format(currentDate) &&
formattedDay == DateFormat('E').format(currentDate);
.
int selectedCardIndex = -1;
bool isSelected = selectedCardIndex == index;
return InkWell(
onTap: () {
setState(() {
selectedCardIndex = index;
selectedCardIndex > 0 ? isSelected : false;
});
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 20),
child: Card(
elevation: 2,
color: isToday
? Color(0xff9a9a9a)
: isSelected
? Colors.black
: Color(0xffF8F8F8),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Container(
height: MediaQuery.of(context).size.height * 0.1,
width: MediaQuery.of(context).size.width * 0.12,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
formattedDate,
style: TextStyle(
fontSize: 18,
color: isToday || isSelected
? Colors.white
: Colors.black,
),
),
Text(
formattedDay.toUpperCase(),
style: TextStyle(
fontSize: 10,
color: isToday
? Colors.white
: isSelected
? Colors.black
: Color(0xff8EA0B6),
),
),
Text(
(isToday && isSelected) ? '˚' : '',
style: TextStyle(color: Colors.white),
)
],
),
),
),
),
);
},
separatorBuilder: (BuildContext context, int index) =>
SizedBox(width: 4),
itemCount: 30,
));
}
I used a regular expression, and the part I focused on is the onTap section.
Through this part, I made it return true when the value is less than 0, and I intended to give black color and white text only to those where isSelected is true.
onTap: () {
setState(() {
selectedCardIndex = index;
selectedCardIndex > 0 ? isSelected : false;
});
...
color: isToday
? Color(0xff9a9a9a)
: isSelected
? Colors.black
: Color(0xffF8F8F8),
...
color: isToday
? Colors.white
: isSelected
? Colors.black
: Color(0xff8EA0B6),
),
),
Text(
(isToday && isSelected) ? '˚' : '',
style: TextStyle(color: Colors.white),
)
I attempted to use a regular expression for the conditional statement, but all attempts failed. I want the card to change to a black background when clicked, and return to its original state when clicked again. How can I achieve this? Please provide advice.
2
Answers
You are declaring all variables within the function which is pointless because after a
setState
it will just go to the lineagain. So you need to declare it outside the function.
Also, this line:
does nothing at all. You are saying it’s returning a value but it’s not. Maybe you are thinking of
kotlin
where the last expression in a block is the return value, this doesn’t happen indart
. But it wouldn’t matter anyway because you can’t return any values from asetState
.I’m not entirely sure if you needed that only one item is selectable or more, but if it’s just one then as I said you need to declare
selectedCardIndex
outside the function and you can change theonTap
toIf you want to able to select multiple you could use a set instead for example, so declare
(outside the function) and this as
onTap
and change
isSelected
toUse this code I have tried it, and it is working according to my understanding let me know if I got the logic wrong.