Flutter - 在一个屏幕上显示两个 ListView

Posted

技术标签:

【中文标题】Flutter - 在一个屏幕上显示两个 ListView【英文标题】:Flutter - Displaying two ListViews on one screen 【发布时间】:2019-01-25 09:38:25 【问题描述】:

我正在尝试在另一个垂直 listView.builder 之上添加一个水平 listView.builder。两个listViews 都应该有text

这是我到目前为止所做的,只有顶部水平 listView.builder 被绘制,当我尝试点击底部时强> 垂直listView.builder 应该被绘制,应用程序在调试中崩溃,我得到错误:NoSuchMethodError: The getter 'visible' was called on null.

另外,我不知道如何添加两个 text 字段,所以我把它们省略了。

我有很多代码,如果您需要查看更多代码,请这样做here

Widget _cryptoWidget() 
return new Container(
    child: new Column(
      children: <Widget>[
        new Flexible(
          child: new ListView.builder(
              scrollDirection: Axis.horizontal,
              itemBuilder: (BuildContext context, int index) 
              return _listViewFiller();
            
          ),
        ),
        new Flexible(
          child: new RefreshIndicator(
          key: refreshKey,
          child: new ListView.builder(
            scrollDirection: Axis.horizontal,
            itemCount: _currencies.length,
            itemBuilder: (BuildContext context, int index) 
              final int i = index ~/ 2;
              final Crypto currency = _currencies[i];
              final MaterialColor color = _colors[i % _colors.length];
              if (index.isOdd) 
                return new Divider();
              
              return _getListItemUi(currency, color);
            ,
          ),
          onRefresh:refreshList,
        ),
        )
      ],
    )
  );
 

【问题讨论】:

两个listview都是Axis.horizo​​ntal 我已经解决了这个问题,很快就会回答我自己的问题 只需要修复一些位置错误 我的问题现已发布 尝试将列表视图放入 scoolview 小部件中。并检查this,*** 上的相同问题 【参考方案1】:
import 'package:flutter/material.dart';
import 'background.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget 
@override
Widget build(BuildContext context) 
return new MaterialApp(
  title: 'Flutter Demo',
  theme: new ThemeData(
    primarySwatch: Colors.blue,
  ),
  debugShowCheckedModeBanner: false,
  home: new MyHomePage(title: 'Popular'),
);



class MyHomePage extends StatefulWidget 
MyHomePage(Key key, this.title) : super(key: key);

final String title;

@override
_MyHomePageState createState() => new _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 
List<String> items = [
"Item 1",
"Item 2",
"Item 3",
"Item 4",
"Item 5",
"Item 6",
"Item 7",
"Item 8"
];

@override
Widget build(BuildContext context) 
final _width = MediaQuery.of(context).size.width;
final _height = MediaQuery.of(context).size.height;

final headerList = new ListView.builder(
  itemBuilder: (context, index) 
    EdgeInsets padding = index == 0?const EdgeInsets.only(
        left: 20.0, right: 10.0, top: 4.0, bottom: 30.0):const EdgeInsets.only(
        left: 10.0, right: 10.0, top: 4.0, bottom: 30.0);
    
    return new Padding(
      padding: padding,
      child: new InkWell(
        onTap: () 
          print('Card selected');
        ,
        child: new Container(
          decoration: new BoxDecoration(
            borderRadius: new BorderRadius.circular(10.0),
            color: Colors.lightGreen,
            boxShadow: [
              new BoxShadow(
                  color: Colors.black.withAlpha(70),
                  offset: const Offset(3.0, 10.0),
                  blurRadius: 15.0)
            ],
            image: new DecorationImage(
              image: new ExactAssetImage(
                  'assets/img_$index%items.length.jpg'),
              fit: BoxFit.fitHeight,
            ),
          ),
        //                                    height: 200.0,
          width: 200.0,
          child: new Stack(
            children: <Widget>[
              new Align(
                alignment: Alignment.bottomCenter,
                child: new Container(
                    decoration: new BoxDecoration(
                        color: const Color(0xFF273A48),
                        borderRadius: new BorderRadius.only(
                            bottomLeft: new Radius.circular(10.0),
                            bottomRight: new Radius.circular(10.0))),
                    height: 30.0,
                    child: new Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        new Text(
                          '$items[index%items.length]',
                          style: new TextStyle(color: Colors.white),
                        )
                      ],
                    )),
              )
            ],
          ),
        ),
      ),
    );
  ,
  scrollDirection: Axis.horizontal,
  itemCount: items.length,
);

final body = new Scaffold(
  appBar: new AppBar(
    title: new Text(widget.title),
    elevation: 0.0,
    backgroundColor: Colors.transparent,
    actions: <Widget>[
      new IconButton(icon: new Icon(Icons.shopping_cart, color: Colors.white,), onPressed: ())
    ],
  ),
  backgroundColor: Colors.transparent,
  body: new Container(
    child: new Stack(
      children: <Widget>[
        new Padding(
          padding: new EdgeInsets.only(top: 10.0),
          child: new Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              new Align(
                alignment: Alignment.centerLeft,
                child: new Padding(
                    padding: new EdgeInsets.only(left: 8.0),
                    child: new Text(
                      'Recent Items',
                      style: new TextStyle(color: Colors.white70),
                    )),
              ),
              new Container(
                  height: 300.0, width: _width, child: headerList),
              new Expanded(child:
              ListView.builder(itemBuilder: (context, index) 
                return new ListTile(
                  title: new Column(
                    children: <Widget>[
                      new Row(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          new Container(
                            height: 72.0,
                            width: 72.0,
                            decoration: new BoxDecoration(
                                color: Colors.lightGreen,
                                boxShadow: [
                                  new BoxShadow(
                                      color:
                                      Colors.black.withAlpha(70),
                                      offset: const Offset(2.0, 2.0),
                                      blurRadius: 2.0)
                                ],
                                borderRadius: new BorderRadius.all(
                                    new Radius.circular(12.0)),
                                image: new DecorationImage(
                                  image: new ExactAssetImage(
                                    'assets/img_$index%items.length.jpg',
                                  ),
                                  fit: BoxFit.cover,
                                )),
                          ),
                          new SizedBox(
                            width: 8.0,
                          ),
                          new Expanded(
                              child: new Column(
                                mainAxisAlignment:
                                MainAxisAlignment.start,
                                crossAxisAlignment:
                                CrossAxisAlignment.start,
                                children: <Widget>[
                                  new Text(
                                    'My item header',
                                    style: new TextStyle(
                                        fontSize: 14.0,
                                        color: Colors.black87,
                                        fontWeight: FontWeight.bold),
                                  ),
                                  new Text(
                                    'Item Subheader goes here\nLorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry',
                                    style: new TextStyle(
                                        fontSize: 12.0,
                                        color: Colors.black54,
                                        fontWeight: FontWeight.normal),
                                  )
                                ],
                              )),
                          new Icon(
                            Icons.shopping_cart,
                            color: const Color(0xFF273A48),
                          )
                        ],
                      ),
                      new Divider(),
                    ],
                  ),
                );
              ))
            ],
          ),
        ),
      ],
    ),
  ),
);

return new Container(
  decoration: new BoxDecoration(
    color: const Color(0xFF273A48),
  ),
  child: new Stack(
    children: <Widget>[
      new CustomPaint(
        size: new Size(_width, _height),
        painter: new Background(),
        ),
       body,
      ],
    ),
  );
 

一个很好的例子,这里有完整的源代码 Styled list

【讨论】:

哈哈这比我自己的答案还要好!感谢您的帮助 如何隐藏一种布局?【参考方案2】:

此示例代码在单个页面中显示了两个垂直方向的listview,两个lisview数据都来自API 我单独设计了一个列表项小部件或模板(ListItemPosts)。

body: ListView(
              children: <Widget>[
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    SizedBox(height: 10.0),
                    new Container(
                      margin: EdgeInsets.only(left: 10.0,right: 10.0),
                      height: 40.0, width: double.infinity,
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(25.0),
                          color: Colors.green.withOpacity(0.25)
                      ),
                    child:Padding(
                      padding: const EdgeInsets.only(left: 15.0,right: 15.0,top: 8.0),


                      child: Text(
                        'Invoiced Products',
                        style: TextStyle(
                            fontFamily: 'Quicksand',
                            fontSize: 20.0,
                            color: Colors.green,
                            fontWeight: FontWeight.bold),
                        textAlign: TextAlign.center,
                      ),
                    ), 
                    ),

                    SizedBox(height: 5.0),
                    FutureBuilder<List<SalesOrder>>(
                      future: fetchstring(http.Client()),
                      builder: (context, snapshot) 
                        if (snapshot.hasError) print(snapshot.error);
                        return snapshot.hasData ? ListItemPosts(
                            items: snapshot.data)
                            : Center(child: CircularProgressIndicator());
                      ,
                    ),
                    SizedBox(height: 10.0)
                  ],
                ),
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    SizedBox(height: 10.0),
                    new Container(
                      margin: EdgeInsets.only(left:10.0,right: 10.0),
                      height: 40.0, width: double.infinity,
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(25.0),
                          color: Colors.red.withOpacity(0.25)
                      ),
                      child:Padding(
                        padding: const EdgeInsets.only(left: 15.0,right: 15.0,top: 8.0),
                        child: Text(
                          'Pending Products',
                          style: TextStyle(
                              fontFamily: 'Quicksand',
                              fontSize: 20.0,
                              color: Colors.red,
                              fontWeight: FontWeight.bold),
                          textAlign: TextAlign.center,
                        ),
                      ),
                    ),

                    SizedBox(height: 5.0),
                    FutureBuilder<List<SalesOrder>>(
                      future: fetchstring(http.Client()),
                      builder: (context, snapshot) 
                        if (snapshot.hasError) print(snapshot.error);
                        return snapshot.hasData ? ListItemPosts(
                            items: snapshot.data)
                            : Center(child: CircularProgressIndicator());
                      ,
                    ),
                    SizedBox(height: 10.0)
                  ],
                )
              ],
            )

ListitemPost(小部件)

class ListItemPosts extends StatelessWidget 
  final List<SalesOrder> items;
  ListItemPosts(Key key, this.items) : super(key: key);
  @override
  Widget build(BuildContext context) 
    return Container(

        child: new ListView.builder(
            itemCount:  items[0].sodetails.length,
            primary: false,
            shrinkWrap: true,

            itemBuilder: (BuildContext context, int position) 
              return new  Column(
                children: <Widget>[
                  Divider(height: 5.0),
                  listItem(your Data can pass),
                ],
              );


            )

    );

  



Widget listItem(Get the data ) 
  return Container(
    height: 125.0,
    width: double.infinity,

    margin: EdgeInsets.only(left: 10.0,right: 10.0),
    decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(12.0),
      color: Colors.white,
    ),
    child:
    Row(
      children: <Widget>[
        /*Container(
          decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(12.0),
              image:
              DecorationImage(image: AssetImage(imagedata))),
          height: 100.0,
          width: 80.0,
        ),*/

        SizedBox(width: 0.0),
        Container(
          width: MediaQuery.of(context).size.width -30.0,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Flexible(child:
                  Text(
                    imagename,
                    textAlign: TextAlign.left,
                    softWrap: false,
                    style: TextStyle(fontFamily: 'Quicksand',fontSize: 14.0,color: Colors.black),
                  )),
                  SizedBox(height: 5.0),
                  Flexible(child:
                  Text(
                    trim.stringtrim(imagedes),
                    overflow: TextOverflow.ellipsis,
                    maxLines: 2,
                    style: TextStyle(fontFamily: 'Quicksand',fontSize: 12.0,color: Colors.black45),
                  ),
                  ),
                  SizedBox(height: 5.0),
                  Text(
                    'Price: '+Price.toString(),
                    style: TextStyle(fontFamily: 'Quicksand'),
                  ),
                  SizedBox(height: 5.0),
                  Text(
                    'Qty: '+Quatity.toString(),
                    style: TextStyle(fontFamily: 'Quicksand'),
                  ),
                  SizedBox(height: 5.0),
                  Container(
                    height: 2.0,
                    width: 100.0,
                    color: Colors.amber,
                  ),

                ],
              ),

            ],
          ),
        ),

      ],
    ),
  );

【讨论】:

【参考方案3】:

这可能不是最干净的方法,但我对 Flutter 比较陌生,所以这是我能做的最好的。

首先,我创建了一个主 container 来传递所有信息,这样我就可以将所有相关代码保存在他们尊重的地方,这篇文章允许我在同一个 container 中显示两个 listViews

这是传递给_positonalArgumentscontainers 之一。这让我可以防止元素溢出,例如 maxHeight: 335.0, 是一个严格的参数,由于反复试验而发现。

我在传递给_positionalArguments 的两个容器中使用了相同的BoxConstraints,以及相同的margin 值。

抱歉,我使用的是图像而不是粘贴代码,我正在使用手机上的堆栈来回答这个问题。

【讨论】:

以上是关于Flutter - 在一个屏幕上显示两个 ListView的主要内容,如果未能解决你的问题,请参考以下文章

在flutter中缓存两个List

来自一个 StreamBuilder 的 Flutter 快照显示在另一个 StreamBuilder 中

如何在 Flutter 的同一屏幕中管理两个带有数据的 ListView

如何在 Flutter 中一次只在屏幕上显示一个表单域?

如何使页面的背景半透明以在 Flutter 中显示上一个屏幕?

Flutter 小部件显示在所有屏幕上