I want to mark my object as favorite.
I have a list of object <RobotAnimation>
which is displayed in a ListView
. The class have two fields: title
and isFavorite
. Marking an object as a favorite works, but there is a problem when it comes to storing that state. When I perform a search of all items, after selecting an item as favorite, my favorite items are not being remembered. It seems like the state is being discarded.
What can I do to fix this problem?
Here's what's going on:
Here's my code:
class RobotAnimation {
String title;
bool isFavorite;
RobotAnimation({required this.title, this.isFavorite = false});
@override
String toString() {
return '{Title: $title, isFavortite: $isFavorite}';
}
}
class Animations extends StatefulWidget {
const Animations({super.key});
@override
State<Animations> createState() => _AnimationsState();
}
class _AnimationsState extends State<Animations> with TickerProviderStateMixin {
late TabController _tabController;
List<RobotAnimation> animations = [];
List<RobotAnimation> favoriteAnimations = [];
List<String> results = store.state.animations;
List<String> defaultFavorites = [];
List<RobotAnimation> getAnimationList(
List<String> animations, List<String> favorites) {
List<RobotAnimation> robotAnimations = [];
for (var animation in animations) {
bool isFav = false;
for (var favorite in favorites) {
if (favorite == animation) {
isFav = true;
}
}
robotAnimations.add(RobotAnimation(title: animation, isFavorite: isFav));
}
return robotAnimations;
}
List<RobotAnimation> filterFavorites() {
List<RobotAnimation> filtered = favoriteAnimations;
animations.where((element) => element.isFavorite == true).toList();
return filtered;
}
void filterSearchResults(String query) {
List<RobotAnimation> searchList =
getAnimationList(results, defaultFavorites);
log('query: $query');
List<RobotAnimation> filteredList = searchList
.where((element) =>
element.title.toLowerCase().contains(query.toLowerCase()))
.toList();
log(searchList.toString());
log(filteredList.toString());
setState(() => animations = filteredList);
}
@override
void initState() {
animations = getAnimationList(results, defaultFavorites);
super.initState();
}
@override
Widget build(BuildContext context) {
return StoreConnector<AppState, _Props>(
converter: (store) => _mapStateToProps(store),
builder: (_, props) {
return Scaffold(
body: TabBarView(
...
children: [
Container(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
TextField(
onChanged: filterSearchResults,
decoration: const InputDecoration(
labelText: 'Search',
hintText: 'Search animation',
prefixIcon: Icon(Icons.search),
),
),
Expanded(
child: ListView.separated(
itemCount: animations.length,
separatorBuilder: (context, index) => const Divider(),
itemBuilder: (context, index) {
return ListTile(
onTap: () {
props.socket?.animation(IAnimation(
animation: animations[index].title));
},
title: ExtendedText(
animations[index].title,
maxLines: 1,
overflowWidget: const TextOverflowWidget(
position: TextOverflowPosition.middle,
align: TextOverflowAlign.center,
child: Text(
'...',
overflow: TextOverflow.ellipsis,
),
),
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: () {
setState(() {
animations[index].isFavorite
? animations[index].isFavorite = false
: animations[index].isFavorite = true;
});
},
icon: animations[index].isFavorite
? Icon(
Icons.favorite,
color: Colors.red.shade500,
)
: Icon(
Icons.favorite_border,
color: Colors.grey.shade500,
),
),
],
),
);
},
),
)
],
),
),
],
),
);
},
);
}
}
class _Props {
final Connection? socket;
final List<String> animations;
_Props({
required this.socket,
required this.animations,
});
}
_Props _mapStateToProps(Store<AppState> store) {
return _Props(
socket: store.state.socket,
animations: store.state.animations,
);
}
CodePudding user response:
Try this inside your IconButton
onPressed
-Method:
setState(() {
if (animations[index].isFavorite) {
animations[index].isFavorite = false
defaultFavorites.remove(animations[index].title)
} else {
animations[index].isFavorite = true;
defaultFavorites.add(animations[index].title)
}
});
It seems like you always generate a new list of animations based on the two lists List<String>
.