Flutter ListView选中项状态保持及'isSelected'报错问题求助
Hey, let's break down what's going wrong here and fix it up smoothly!
Why You're Seeing This Error
Your physical_status list is made up of plain String values ('0', '1', '2'), and the String class in Dart doesn't have an isSelected property built-in. When you try to access physical_status[index].isSelected, the compiler has no clue what you're referring to—that's exactly why you're getting this error.
We've got two straightforward fixes, depending on how you want to structure your data.
Solution 1: Track Selected Index (Simplest Approach)
Instead of trying to attach properties to Strings, just keep track of which list index is currently selected with a separate variable. Here's how to adjust your code:
Replace your
bool isSelected = false;with:int? selectedIndex; // Stores the index of the selected item; null means no selectionUpdate the
onTaphandler to set the selected index when an item is tapped:onTap: () { setState(() { selectedIndex = index; // Mark the tapped item's index as selected }); },Change the color condition to check if the current index matches the selected one:
color: selectedIndex == index ? Colors.red[100] : Colors.white,
Full Modified Code
final List<String> physical_status = <String>['0', '1', '2']; int? selectedIndex; // Updated selection tracker @override Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; return SingleChildScrollView( // Don't forget the return statement! scrollDirection: Axis.horizontal, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Container( height: 110, width: size.width, child: ListView.builder( shrinkWrap: true, scrollDirection: Axis.horizontal, itemCount: physical_status.length, // Added to prevent infinite list building itemBuilder: (BuildContext context, int index) { return Padding( padding: const EdgeInsets.all(10.0), child: GestureDetector( onTap: () { print("clicked"); setState(() { selectedIndex = index; }); }, child: Container( width: 100, height: 100, color: selectedIndex == index ? Colors.red[100] : Colors.white, decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage( fit: BoxFit.cover, image: AssetImage("assets/images/user_avatar.png") ), ), ), ), ); }, ), ), ], ), ); }
Quick note: I added itemCount: physical_status.length to your ListView.builder—without this, it would try to build infinitely many items, which is a common Flutter gotcha!
Solution 2: Use a Custom Data Class (Scalable for Future Features)
If you might need to add more properties to your list items later (like labels, icons, or additional states), creating a custom class is the cleaner, more scalable approach:
Define a class to hold your status item data and selection state:
class PhysicalStatusItem { final String id; bool isSelected; PhysicalStatusItem({required this.id, this.isSelected = false}); }Update your list to use this new class:
final List<PhysicalStatusItem> physical_status = [ PhysicalStatusItem(id: '0'), PhysicalStatusItem(id: '1'), PhysicalStatusItem(id: '2'), ];Modify the
onTaphandler to deselect all items first, then select the tapped one:onTap: () { setState(() { // Deselect every item in the list for (var item in physical_status) { item.isSelected = false; } // Select the tapped item physical_status[index].isSelected = true; }); },Your color condition can stay almost identical (now it's valid because
PhysicalStatusItemhas anisSelectedproperty):color: physical_status[index].isSelected ? Colors.red[100] : Colors.white,
This approach keeps your data organized and makes it easy to extend later if you need to add more features to your list items.
内容的提问来源于stack exchange,提问作者Abhijith

