Skip to content

[Bug Fix] Selection highlighting breaks in long lists due to Widget Recycling (Missing Keys) #28

@p5ych0p41h

Description

@p5ych0p41h

Description:
Hello! Thanks for this great library.

I encountered a visual bug when using a dropdownList with many items (e.g., more than 15-20 items). When scrolling down the list, items that are not selected appear with the "selected" style (e.g., grey background), while the actual selected item might lose its highlighting.

The Problem:
This is a classic Flutter ListView recycling issue.

  1. DropdownWidget uses ListView.builder.
  2. DropdownItemWidget is a StatefulWidget that holds an AnimationController for the selection effect.
  3. When scrolling, Flutter recycles the State of widgets that go off-screen to render new items coming on-screen.
  4. Since DropdownItemWidget does not have a unique Key, Flutter reuses the State of a previously rendered item. If the previous item was selected (Animation value 1.0), the new item reusing that state will also appear selected, even if item.isSelected is false.

The Fix:
I have implemented a fix that solves this by doing two things:

  1. Assigning a unique ValueKey to each DropdownItemWidget so Flutter knows they are different entities.
  2. Initializing the animation value in initState to ensure correct rendering when a widget is first built.

Here are the changes needed:

1. lib/widgets/dropdown_widget.dart

In the itemBuilder, add a key:

// ... inside ListView.builder
itemBuilder: (_, index) => GestureDetector(
  onTap: () {
    // ...
  },
  child: Column(
    children: [
      // ...
      DropdownItemWidget(
        // [FIX] Add a unique Key here! 
        // This prevents the State (and AnimationController) from being reused incorrectly.
        key: ValueKey(widget.dropdownList[index].hashCode), 
        
        item: widget.dropdownList[index],
        dropdownItemOptions: widget.dropdownItemOptions,
      ),
      // ...
    ],
  ),
),

2. lib/widgets/dropdown_item_widget.dart

Initialize the controller value in initState. Without this, if you scroll to a pre-selected item that wasn't initially on screen, it might animate from 0 instead of being already highlighted.

class _DropdownItemWidgetState extends State<DropdownItemWidget>
    with SingleTickerProviderStateMixin {
  
  // ... controller definitions ...

  // [FIX] Add initState
  @override
  void initState() {
    super.initState();
    // Immediately set the animation state if the item is already selected
    if (widget.item.isSelected) {
      _controller.value = 1.0;
    }
  }

  // ... dispose and build methods ...
}

With these changes, the dropdown works perfectly with lists of any size (tested with 20+ items).

Hope this helps!

P.S. I'm really looking forward to the library update!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions