prefer-using-list-view

Path
lint/performance/prefer-using-list-view
Default
Off, opt in
Origin
Falcon
Domain
flutter
Rule
419 of 512
flutter

Suggests considering ListView for a SingleChildScrollView containing a plain Flutter Column with at least two unconditional children in a list literal. Spreads, control-flow elements and dynamic lists do not establish that minimum. This is not a layout-neutral replacement: preserve the Column's child alignment and scroll view's padding explicitly. ListView stretches children across the cross axis and adds MediaQuery padding by default. For the default Column alignment, wrap each list child in an Align with Alignment.topCenter; use the original scroll padding, or EdgeInsets.zero when none was supplied. Review constraints and child lifecycle separately. No automatic fix is offered.

Invalid

example.dartdart
import 'package:flutter/widgets.dart';
import 'package:flutter/widgets.dart' as f;
typedef V = SingleChildScrollView;
void callback() {}
void examples(Widget child, dynamic image, dynamic color, double size, String label) {
  SingleChildScrollView(child: Column(children: [child, child]));
  const SingleChildScrollView(child: Column(children: [Text('a'), Text('b')]));
  new SingleChildScrollView(child: Column(children: [child, child]));
  f.SingleChildScrollView(child: f.Column(children: [child, child]));
  V(child: Column(children: [child, child]));
  SingleChildScrollView(child: Column(children: [Text('a'), Text('much longer')]));
  SingleChildScrollView(child: Column(children: ([child, child])));
  SingleChildScrollView(child: Column(children: [child, ...<Widget>[], child]));
  SingleChildScrollView(child: Column(children: [child, if (size > 0) child, child]));
  SingleChildScrollView(child: Column(children: [child, for (final item in <Widget>[]) item, child]));
  SingleChildScrollView(child: Column(children: <Widget>[child, child]));
}
Consider `ListView` for this scrollable `Column`; preserve child alignment and padding explicitly, including `ListView`'s default `MediaQuery` padding.
5void examples(Widget child, dynamic image, dynamic color, double size, String label) {
6 SingleChildScrollView(child: Column(children: [child, child]));
Consider `ListView` for this scrollable `Column`; preserve child alignment and padding explicitly, including `ListView`'s default `MediaQuery` padding.
6 SingleChildScrollView(child: Column(children: [child, child]));
7 const SingleChildScrollView(child: Column(children: [Text('a'), Text('b')]));
Consider `ListView` for this scrollable `Column`; preserve child alignment and padding explicitly, including `ListView`'s default `MediaQuery` padding.
7 const SingleChildScrollView(child: Column(children: [Text('a'), Text('b')]));
8 new SingleChildScrollView(child: Column(children: [child, child]));
Consider `ListView` for this scrollable `Column`; preserve child alignment and padding explicitly, including `ListView`'s default `MediaQuery` padding.
8 new SingleChildScrollView(child: Column(children: [child, child]));
9 f.SingleChildScrollView(child: f.Column(children: [child, child]));
Consider `ListView` for this scrollable `Column`; preserve child alignment and padding explicitly, including `ListView`'s default `MediaQuery` padding.
9 f.SingleChildScrollView(child: f.Column(children: [child, child]));
10 V(child: Column(children: [child, child]));
Consider `ListView` for this scrollable `Column`; preserve child alignment and padding explicitly, including `ListView`'s default `MediaQuery` padding.
10 V(child: Column(children: [child, child]));
11 SingleChildScrollView(child: Column(children: [Text('a'), Text('much longer')]));
Consider `ListView` for this scrollable `Column`; preserve child alignment and padding explicitly, including `ListView`'s default `MediaQuery` padding.
11 SingleChildScrollView(child: Column(children: [Text('a'), Text('much longer')]));
12 SingleChildScrollView(child: Column(children: ([child, child])));
Consider `ListView` for this scrollable `Column`; preserve child alignment and padding explicitly, including `ListView`'s default `MediaQuery` padding.
12 SingleChildScrollView(child: Column(children: ([child, child])));
13 SingleChildScrollView(child: Column(children: [child, ...<Widget>[], child]));
Consider `ListView` for this scrollable `Column`; preserve child alignment and padding explicitly, including `ListView`'s default `MediaQuery` padding.
13 SingleChildScrollView(child: Column(children: [child, ...<Widget>[], child]));
14 SingleChildScrollView(child: Column(children: [child, if (size > 0) child, child]));
Consider `ListView` for this scrollable `Column`; preserve child alignment and padding explicitly, including `ListView`'s default `MediaQuery` padding.
14 SingleChildScrollView(child: Column(children: [child, if (size > 0) child, child]));
15 SingleChildScrollView(child: Column(children: [child, for (final item in <Widget>[]) item, child]));
Consider `ListView` for this scrollable `Column`; preserve child alignment and padding explicitly, including `ListView`'s default `MediaQuery` padding.
15 SingleChildScrollView(child: Column(children: [child, for (final item in <Widget>[]) item, child]));
16 SingleChildScrollView(child: Column(children: <Widget>[child, child]));

Valid

example.dartdart
import 'package:flutter/widgets.dart';
import 'package:flutter/widgets.dart' as f;
typedef V = SingleChildScrollView;
void callback() {}
void examples(Widget child, dynamic image, dynamic color, double size, String label) {
  ListView(children: [child]);
  SingleChildScrollView(child: Row());
  SingleChildScrollView(child: child);
  Column(children: [child]);
  SingleChildScrollView();
  SingleChildScrollView(child: Column());
  const SingleChildScrollView(child: Column(children: []));
  new SingleChildScrollView(child: Column(children: [child]));
  f.SingleChildScrollView(child: f.Column(children: <Widget>[]));
  V(child: Column(children: [child]));
  SingleChildScrollView(child: Column(children: ([child])));
  SingleChildScrollView(child: Column(children: <Widget>[child]));
  SingleChildScrollView(child: Column(children: [...<Widget>[]]));
  SingleChildScrollView(child: Column(children: [...<Widget>[child]]));
  SingleChildScrollView(child: Column(children: [if (size > 0) child]));
  SingleChildScrollView(child: Column(children: [if (size > 0) child else child]));
  SingleChildScrollView(child: Column(children: [for (final item in <Widget>[]) item]));
  SingleChildScrollView(child: Column(children: [child, ...<Widget>[]]));
  SingleChildScrollView(child: Column(children: [child, if (size > 0) child]));
  SingleChildScrollView(child: Column(children: image));
  SingleChildScrollView(child: Column(children: image ? <Widget>[] : <Widget>[child]));
  SingleChildScrollView(child: Column(children: [child, ...image]));
  SingleChildScrollView(child: Column(children: [child, ...?image]));
  SingleChildScrollView(child: Column(children: [child, ?image]));
  SingleChildScrollView(child: Column(children: [for (final item in <Widget>[]) item, child]));
}

Configure prefer-using-list-view

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "performance": {
        "prefer-using-list-view": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/performance/prefer-using-list-view: <reason>