简体   繁体   中英

Why can't ListView be a child of a Column layout in flutter inside a Dialog?

I'm trying to show a ListView inside a flutter dialog. This is causing a crash when the ListView's has the following parent hierarchy

 Dialog
   Column
     children:
       ListView    <- crash exists here. 
       

The weird thing is if i manually create the list items(without using a listView builder) there is no problem and everything is layed out as expected. But using a ListView, the UI freezes

This is where is issue is happening

return Dialog(
      elevation: 2.0,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          // MANUAL creation: completely fine
          __Item(),
          __Item(),
          /*
          // ListView creation causes crash
          ListView.builder(
            itemCount: 2,
            itemBuilder: (context, index) => __Item(),
          ),
          */
        ],
      ),
    );

I get the following exception dump

════════ Exception caught by rendering library ═════════════════════════════════
Assertion failed:
../…/rendering/box.dart:1930
hasSize
"RenderBox was not laid out: RenderCustomPaint#fe985 relayoutBoundary=up7 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE"

The relevant error-causing widget was
ListView
lib/main.dart:39
════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by rendering library ═════════════════════════════════
Assertion failed:
../…/rendering/box.dart:1930
hasSize
"RenderBox was not laid out: RenderRepaintBoundary#53baa relayoutBoundary=up6 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE"

The relevant error-causing widget was
Column
lib/main.dart:31

The full reproducable version is

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(home: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => showDialog(
            context: context,
            builder: (c) => TestDialog(),
          ),
          child: Text('Launch Dialog'),
        ),
      ),
    );
  }
}

class TestDialog extends StatelessWidget {
  const TestDialog({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Dialog(
      elevation: 2.0,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          __Item(),
          __Item(),
          /*
          // uncomment to see crash
          ListView.builder(
            itemCount: 3,
            itemBuilder: (context, index) => __Item(),
          ),
          */
        ],
      ),
    );
  }
}

class __Item extends StatelessWidget {
  const __Item({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
        margin: EdgeInsets.only(top: 10.0),
        width: 100.0,
        height: 20.0,
        color: Colors.red,
        child: Center(child: Text("Test child")));
  }
}

NOTE: i'm testing it in Chrome view

Wrap the ListView using the Expanded .

Dialog(
  elevation: 2.0,
  child: Column(
    mainAxisSize: MainAxisSize.min,
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [
      __Item(),
      __Item(),
      Expanded(
        child: ListView.builder(
          itemCount: 100,
          itemBuilder: (context, index) => __Item(),
        ),
      ),
    ],
  ),
);

The problem ist that the vertical viewport hast a unbounded height. The view ports expand in the scrolling direction to fill their container. In this case, a vertical viewport was given an unlimited amount of vertical space in which to expand. This situation typically happens when a scrollable widget is nested inside another scrollable widget.

You must always to limit the height of the Column widget with another Widget, which doesn't expand in a unlimited way.

return Dialog(
      elevation: 2.0,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          //__Item(),
          //__Item(),
          // uncomment to see crash
          Expanded(
            child: ListView.builder(
              itemCount: 3,
              itemBuilder: (context, index) => __Item(),
            ),
          ),
        ],
      ),
    );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM