You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter ListView选中项状态保持及'isSelected'报错问题求助

Fixing the "isSelected isn't defined for String" Error in Your Flutter ListView

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:

  1. Replace your bool isSelected = false; with:

    int? selectedIndex; // Stores the index of the selected item; null means no selection
    
  2. Update the onTap handler to set the selected index when an item is tapped:

    onTap: () {
      setState(() {
        selectedIndex = index; // Mark the tapped item's index as selected
      });
    },
    
  3. 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:

  1. 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});
    }
    
  2. Update your list to use this new class:

    final List<PhysicalStatusItem> physical_status = [
      PhysicalStatusItem(id: '0'),
      PhysicalStatusItem(id: '1'),
      PhysicalStatusItem(id: '2'),
    ];
    
  3. Modify the onTap handler 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;
      });
    },
    
  4. Your color condition can stay almost identical (now it's valid because PhysicalStatusItem has an isSelected property):

    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 17:57:39