จะเพิ่ม ListView ไปยังคอลัมน์ใน Flutter ได้อย่างไร?


140

ฉันกำลังพยายามสร้างหน้าเข้าสู่ระบบอย่างง่ายสำหรับแอป Flutter ของฉัน ฉันสร้าง TextFields และปุ่มล็อกอิน / ลงชื่อเข้าใช้สำเร็จแล้ว ฉันต้องการเพิ่ม ListView แนวนอน เมื่อฉันเรียกใช้โค้ดองค์ประกอบของฉันจะหายไปถ้าฉันทำโดยไม่มี ListView ก็ใช้ได้อีกครั้ง ฉันจะทำอย่างถูกต้องได้อย่างไร?

return new MaterialApp(
        home: new Scaffold(
          appBar: new AppBar(
            title: new Text("Login / Signup"),
          ),
          body: new Container(
            child: new Center(
              child: new Column(
              mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  new TextField(
                    decoration: new InputDecoration(
                      hintText: "E M A I L    A D D R E S S"
                    ),
                  ),
                  new Padding(padding: new EdgeInsets.all(15.00)),
                  new TextField(obscureText: true,
                    decoration: new InputDecoration(
                      hintText: "P A S S W O R D"
                    ),
                    ),
                  new Padding(padding: new EdgeInsets.all(15.00)),
                  new TextField(decoration: new InputDecoration(
                    hintText: "U S E R N A M E"
                  ),),
                  new RaisedButton(onPressed: null,
                  child:  new Text("SIGNUP"),),
                  new Padding(padding: new EdgeInsets.all(15.00)),
                  new RaisedButton(onPressed: null,
                  child: new Text("LOGIN"),),
                  new Padding(padding: new EdgeInsets.all(15.00)),
                  new ListView(scrollDirection: Axis.horizontal,
                  children: <Widget>[
                    new RaisedButton(onPressed: null,
                    child: new Text("Facebook"),),
                    new Padding(padding: new EdgeInsets.all(5.00)),
                    new RaisedButton(onPressed: null,
                    child: new Text("Google"),)
                  ],)

                ],
              ),
            ),
            margin: new EdgeInsets.all(15.00),
          ),
        ),
      );

คำตอบ:


81

คุณสามารถตรวจสอบเอาต์พุตคอนโซล มันพิมพ์ข้อผิดพลาด:

การยืนยันต่อไปนี้ถูกโยนทิ้งในระหว่าง performResize (): วิวพอร์ตแนวนอนได้รับความสูงที่ไม่ถูกผูกมัด วิวพอร์ตจะขยายในแกนกากบาทเพื่อเติมคอนเทนเนอร์และบังคับเด็กให้ตรงกับขอบเขตในแกนกากบาท ในกรณีนี้วิวพอร์ตแนวนอนจะได้รับพื้นที่แนวตั้งที่จะขยายได้ไม่ จำกัด

คุณต้องเพิ่มข้อจำกัดความสูงในรายการแนวนอนของคุณ เช่นห่อด้วยความสูง:

Container(
  height: 44.0,
  child: ListView(
    scrollDirection: Axis.horizontal,
    children: <Widget>[
      RaisedButton(
        onPressed: null,
        child: Text("Facebook"),
      ),
      Padding(padding: EdgeInsets.all(5.00)),
      RaisedButton(
        onPressed: null,
        child: Text("Google"),
      )
    ],
  ),
)

7
คำตอบสองข้อถัดไปจะให้อีกสองวิธีแก้ปัญหาและอธิบายว่าเกิดอะไรขึ้น
pashute

310

ฉันมีปัญหานี้เหมือนกัน วิธีแก้ปัญหาของฉันคือใช้Expandedวิดเจ็ตเพื่อขยายพื้นที่ว่าง

new Column(
  children: <Widget>[
    new Expanded(
      child: horizontalList,
    )
  ],
);

3
นี่เป็นวิธีแก้ปัญหาที่ยอดเยี่ยมเพราะช่วยให้สามารถปรับขนาดความสูง / ความกว้างของ ListView ได้เช่นเมื่อคุณต้องการให้ใช้พื้นที่ที่เหลือ ช่วยให้คุณสามารถพิจารณาขนาดหน้าจอที่แตกต่างกันได้เมื่อยากเกินกว่าที่จะทราบความสูง / ความกว้างที่แน่นอน
Daniel Allen

2
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ โซลูชันนี้ช่วยให้ ListView ใช้ส่วนที่เหลือของหน้าจอโดยไม่ต้องจัดการกับคิวรีของสื่อ
Terence Ponce

ฉันยังใหม่เกินไปสำหรับ Flutter ที่จะรู้ว่าทำไมถึงได้ผล แต่ฉันก็ดีใจ ขอบคุณ. ข้อความแสดงข้อผิดพลาดของ Flutter ไม่เป็นประโยชน์ในการอธิบายสาเหตุของปัญหานี้สำหรับผู้ที่ไม่ใช่ผู้เชี่ยวชาญ
devdanke

ขอบคุณคำตอบของคุณช่วยประหยัดเวลาของฉัน
Licat Julius

132

สาเหตุของข้อผิดพลาด:

Columnขยายเป็นขนาดสูงสุดในทิศทางแกนหลัก (แกนแนวตั้ง) และไฟล์ListView.

แนวทางแก้ไข

ดังนั้นคุณต้อง จำกัด ความสูงของไฟล์ListView. มีหลายวิธีในการทำคุณสามารถเลือกที่เหมาะสมกับความต้องการของคุณมากที่สุด


  1. หากคุณต้องการที่จะอนุญาตให้ListViewใช้เวลาที่เหลือทั้งหมดภายในพื้นที่การใช้งานColumnExpanded

    Column(
      children: <Widget>[
        Expanded(
          child: ListView(...),
        )
      ],
    )

  1. หากคุณต้องการที่จะ จำกัด ของคุณListViewบางคุณสามารถใช้heightSizedBox

    Column(
      children: <Widget>[
        SizedBox(
          height: 200, // constrain height
          child: ListView(),
        )
      ],
    )

  1. หากคุณListViewมีขนาดเล็กคุณอาจลองใช้shrinkWrapทรัพย์สินนั้น

    Column(
      children: <Widget>[
        ListView(
          shrinkWrap: true, // use it
        )
      ],
    )

ความสูงของฉันไม่ควรได้รับการแก้ไขและคำตอบอื่น ๆ ไม่ได้ผลสำหรับฉัน = /
Daniel Vilela

1
@DanielVilela ตัวเลือกที่ 1 น่าจะเหมาะกับคุณ ถ้าไม่กรุณาโพสต์เป็นคำถามและถ้าฉันว่างฉันสามารถตอบได้
CopsOnRoad

1
ได้ผล! ขอบคุณ. ฉันต้องใส่ Expanded () ในสถานที่เชิงกลยุทธ์บางแห่ง
Daniel Vilela

ขอบคุณฉันไม่ได้คิดเกี่ยวกับ Expanded
Gilvan André

ขอบคุณสำหรับ shrinkWrap: true ใน ListView ()
Rana Hyder

19

ฉันมีSingleChildScrollViewในฐานะพ่อแม่คนหนึ่งColumnวิดเจ็ตและวิดเจ็ตมุมมองรายการเป็นลูกคนสุดท้าย

การเพิ่มคุณสมบัติเหล่านี้ในมุมมองรายการทำงานให้ฉัน

  physics: NeverScrollableScrollPhysics(),
  shrinkWrap: true,
  scrollDirection: Axis.vertical,

17

วิดเจ็ตแบบขยายจะเพิ่มขนาดให้มากที่สุดเท่าที่จะทำได้ด้วยพื้นที่ว่างเนื่องจาก ListView มีความสูงไม่สิ้นสุดจึงทำให้เกิดข้อผิดพลาด

 Column(
  children: <Widget>[
    Flexible(
      child: ListView(...),
    )
  ],
)

ที่นี่เราควรใช้วิดเจ็ตแบบยืดหยุ่นเนื่องจากจะใช้พื้นที่ที่จำเป็นเท่านั้นเมื่อขยายใช้เต็มหน้าจอแม้ว่าจะมีวิดเจ็ตไม่เพียงพอที่จะแสดงผลแบบเต็มหน้าจอก็ตาม


10

ที่จริงแล้วเมื่อคุณอ่านเอกสาร ListView ควรอยู่ใน Expanded Widget เพื่อให้สามารถทำงานได้

  Widget build(BuildContext context) {
return Scaffold(
    body: Column(
  children: <Widget>[
    Align(
      child: PayableWidget(),
    ),
    Expanded(
      child: _myListView(context),
    )
  ],
));

}


7

ดังที่ผู้อื่นกล่าวไว้ข้างต้น Wrap listview with Expanded เป็นวิธีแก้ปัญหา

แต่เมื่อคุณจัดการกับ Columns ที่ซ้อนกันคุณจะต้อง จำกัด ListView ของคุณไว้ที่ความสูงที่กำหนด (ประสบปัญหานี้มาก)

หากใครมีวิธีแก้ปัญหาอื่นโปรดระบุในความคิดเห็นหรือเพิ่มคำตอบ

ตัวอย่าง

  SingleChildScrollView(
   child: Column(
     children: <Widget>[
       Image(image: ),//<< any widgets added
       SizedBox(),
       Column(
         children: <Widget>[
           Text('header'),  //<< any widgets added
            Expanded(child: 
            ListView.builder(
              //here your code
               scrollDirection: Axis.horizontal,
        itemCount: items.length,
        itemBuilder: (BuildContext context, int index) {
            return Container();
                   } 
         )
        ),
        Divider(),//<< any widgets added
         ],
       ),

     ],
   ), 
  );

ในคอลัมน์ที่ซ้อนกันไม่ได้ใช้การขยายเพียงแค่ใช้คุณสมบัติ shrikWrap: true ฟิสิกส์: NeverScrolPhysics () ใน listView
Mohamed Kamel

5

คุณสามารถใช้FlexและFlexibleวิดเจ็ต ตัวอย่างเช่น:

Flex(
direction: Axis.vertical,
children: <Widget>[
    ... other widgets ...
    Flexible(
        flex: 1,
        child: ListView.builder(
        itemCount: ...,
        itemBuilder: (context, index) {
            ...
        },
        ),
    ),
],

);


0
return new MaterialApp(
    home: new Scaffold(
      appBar: new AppBar(
        title: new Text("Login / Signup"),
      ),
      body: new Container(
        child: new Center(
          child: ListView(
          //mainAxisAlignment: MainAxisAlignment.center,
          scrollDirection: Axis.vertical,
            children: <Widget>[
              new TextField(
                decoration: new InputDecoration(
                  hintText: "E M A I L    A D D R E S S"
                ),
              ),
              new Padding(padding: new EdgeInsets.all(15.00)),
              new TextField(obscureText: true,
                decoration: new InputDecoration(
                  hintText: "P A S S W O R D"
                ),
                ),
              new Padding(padding: new EdgeInsets.all(15.00)),
              new TextField(decoration: new InputDecoration(
                hintText: "U S E R N A M E"
              ),),
              new RaisedButton(onPressed: null,
              child:  new Text("SIGNUP"),),
              new Padding(padding: new EdgeInsets.all(15.00)),
              new RaisedButton(onPressed: null,
              child: new Text("LOGIN"),),
              new Padding(padding: new EdgeInsets.all(15.00)),
              new ListView(scrollDirection: Axis.horizontal,
              children: <Widget>[
                new RaisedButton(onPressed: null,
                child: new Text("Facebook"),),
                new Padding(padding: new EdgeInsets.all(5.00)),
                new RaisedButton(onPressed: null,
                child: new Text("Google"),)
              ],)

            ],
          ),
        ),
        margin: new EdgeInsets.all(15.00),
      ),
    ),
  );

0

นี่คือวิธีการที่ง่ายมาก มีวิธีการที่แตกต่างกันที่จะทำมันเหมือนคุณจะได้รับโดยมีExpanded, SizedboxหรือContainerและมันควรจะใช้ตามความต้องการ

  1. การใช้งานExpanded: เป็นเครื่องมือที่ขยายลูกของหนึ่งRow, ColumnหรือFlexเพื่อให้เด็กเติมพื้นที่ว่าง

    Expanded(
        child: ListView(scrollDirection: Axis.horizontal,
            children: <Widget>[
              OutlineButton(onPressed: null,
                  child: Text("Facebook")),
              Padding(padding: EdgeInsets.all(5.00)),
              OutlineButton(onPressed: null,
                  child: Text("Google")),
              Padding(padding: EdgeInsets.all(5.00)),
              OutlineButton(onPressed: null,
                  child: Text("Twitter"))
            ]),
      ),

โดยใช้Expandedเครื่องมือที่ทำให้เด็กของRow, ColumnหรือFlexขยายให้เต็มพื้นที่ว่างตามแกนหลัก (เช่นแนวนอนสำหรับแถวหรือแนวตั้งสำหรับคอลัมน์)

  1. ใช้SizedBox: กล่องที่มีขนาดระบุ

    SizedBox(
        height: 100,
        child: ListView(scrollDirection: Axis.horizontal,
            children: <Widget>[
              OutlineButton(
                  color: Colors.white,
                  onPressed: null,
                  child: Text("Amazon")
              ),
              Padding(padding: EdgeInsets.all(5.00)),
              OutlineButton(onPressed: null,
                  child: Text("Instagram")),
              Padding(padding: EdgeInsets.all(5.00)),
              OutlineButton(onPressed: null,
                  child: Text("SoundCloud"))
            ]),
     ),

หากกำหนดให้กับเด็กวิดเจ็ตนี้บังคับให้ชายด์มีความกว้างและ / หรือความสูงที่เฉพาะเจาะจง (โดยสมมติว่าผู้ปกครองของวิดเจ็ตนี้อนุญาตให้มีค่า)

  1. การใช้งานContainer: เป็นเครื่องมือที่สะดวกสบายรวมร่วมกันวาดภาพ , การวางตำแหน่งและปรับขนาดวิดเจ็ต

     Container(
        height: 80.0,
        child: ListView(scrollDirection: Axis.horizontal,
            children: <Widget>[
              OutlineButton(onPressed: null,
                  child: Text("Shopify")),
              Padding(padding: EdgeInsets.all(5.00)),
              OutlineButton(onPressed: null,
                  child: Text("Yahoo")),
              Padding(padding: EdgeInsets.all(5.00)),
              OutlineButton(onPressed: null,
                  child: Text("LinkedIn"))
            ]),
      ),

ผลลัพธ์ของทั้งสามจะเป็นแบบนี้

ป้อนคำอธิบายภาพที่นี่


-1

ลองใช้ Slivers:

Container(
    child: CustomScrollView(
      slivers: <Widget>[
        SliverList(
          delegate: SliverChildListDelegate(
            [
              HeaderWidget("Header 1"),
              HeaderWidget("Header 2"),
              HeaderWidget("Header 3"),
              HeaderWidget("Header 4"),
            ],
          ),
        ),
        SliverList(
          delegate: SliverChildListDelegate(
            [
              BodyWidget(Colors.blue),
              BodyWidget(Colors.red),
              BodyWidget(Colors.green),
              BodyWidget(Colors.orange),
              BodyWidget(Colors.blue),
              BodyWidget(Colors.red),
            ],
          ),
        ),
        SliverGrid(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
          delegate: SliverChildListDelegate(
            [
              BodyWidget(Colors.blue),
              BodyWidget(Colors.green),
              BodyWidget(Colors.yellow),
              BodyWidget(Colors.orange),
              BodyWidget(Colors.blue),
              BodyWidget(Colors.red),
            ],
          ),
        ),
      ],
    ),
  ),
)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.