Home > Net >  RangeError when trying to get flutter ExpansionPanel to expand
RangeError when trying to get flutter ExpansionPanel to expand

Time:12-28

I saw the Widget of the Week at https://www.youtube.com/watch?v=2aJZzRMziJc and copied the code to a State class that I cannot get to work.

class SearchResultsPageState extends State<SearchResultsPage> {
  final List<bool> _isOpen = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("test"),
      ),
      body: SingleChildScrollView(
        child: ExpansionPanelList(
          children: [
            ExpansionPanel(
              headerBuilder: (context, isExpanded) => const Text('one'),
              body: const Text('one one\none'),
              isExpanded: _isOpen.isNotEmpty ? _isOpen[0] : false,
            ),
            ExpansionPanel(
              headerBuilder: (context, isExpanded) => const Text('two'),
              body: const Text('two two\ntwo'),
              isExpanded: _isOpen.isNotEmpty ? _isOpen[1] : false,
            ),
          ],
          expansionCallback: (i, isOpen) => setState(() {
            _isOpen[i] = !isOpen;
          }),
        ),
      ),
    );
  }
}

I have breakpoints at:

isExpanded: _isOpen.isNotEmpty ? _isOpen[0] : false,

isExpanded: _isOpen.isNotEmpty ? _isOpen[1] : false,

expansionCallback: (i, isOpen) => setState(() {
  _isOpen[i] = !isOpen;
}),

The expansionCallback gets called on every click of the button but an Error is thrown and the the isExpanded property is not re-evaluated. The console shows:

The following RangeError was thrown while handling a gesture:
RangeError (index): Invalid value: Valid value range is empty: 0

And it points to:

_isOpen[i] = !isOpen;

What am I missing or doing wrong?

CodePudding user response:

Because your _isOpen list is empty. Initialise list with default values and it will work for you

 final List<bool> _isOpen = [false, false];

For multiple data you can declare it like:

List<bool> _isOpen = List<bool>.filled(10, false);

CodePudding user response:

When working with a Widget that highly depends on boundaries like ListView, ExpansionPanel etc. You should be more careful with null/empty values for the boundaries to avoid errors like "RangeError".

REASON FOR ERROR

In this case, your _isOpen is an empty bool list (final List<bool> _isOpen = [];). And you are trying to get _isOpen[0] or _isOpen[1] if 'isNotEmpty'.

You might be thinking all looks good right? Well NO!!

Dart handles List[index] with valid length. While You are trying to get an index that didn't yet exist after you think you already checked for not being empty.

SOLUTION

Use

final List<bool> _isOpen = [false, false];

Same reason we use

final bool _isLoading = false;

And not longer

final bool _isLoading;

Another way is to use late and initialize the _isOpen later before using it with the ExpansionPanel

late final List<bool> isOpen;
  
isOpen = [false, false];
  • Related