Flutter ListView 与不同的小部件和列表项

Posted

技术标签:

【中文标题】Flutter ListView 与不同的小部件和列表项【英文标题】:Flutter ListView with different widgets and list items 【发布时间】:2019-03-31 16:53:35 【问题描述】:

我不确定我是否遗漏了什么。我正在玩 Flutter,我想用一些文本小部件、按钮和其他小部件构建一个(简单)视图(见下图)。这些小部件后面应该有一个项目列表。整个视图(当然除了应用栏)应该是可滚动的——不仅仅是项目。

这就是我将所有内容都放在 ListView 中的原因。但我不能做这样的事情(而items 是一个带有字符串值的地图):

...    
home: Scaffold(
  appBar: AppBar(
    title: Text('App bar'),
  ),
  body: new ListView(
    children: <Widget>[
      new Text('Some Text'),
      new FlatButton(...),
      new Image.asset(...),
      items.map((item)=>new Padding(
        child: new Text(item.title),
      )).toList()
    ],
  ),
),
...

获得所需视图的正确方法是什么?

提前致谢!

【问题讨论】:

您可以使用 Slivers 来实现这一点,看看 Flutter 团队的一篇精彩文章:medium.com/flutter-io/slivers-demystified-6ff68ab0296f 另一个选项是使用 SingleChildScrollView , Column 并创建 List 并以您想要的顺序以编程方式添加您的项目,在您有一个列表后,设置到您的 Column 的 children 属性中 这里是带有额外小部件的列表视图的一个很好的解决方案:***.com/a/58281604/1068975 docs.flutter.dev/cookbook/lists/mixed-list 【参考方案1】:

ListView 中的子元素是元素的列表,所以,如果你想显示一个按钮或文本,你的小部件树是:

Scaffold
 appBar: AppBar
 body:  Container
   child: ListView       
            ListItem
            ListItem
            ListItem

然后,在您的情况下,您可以使用 Column 来显示“固定小部件”(文本、按钮)+ listview 可滚动:

Scaffold
 appBar: AppBar
 body:  Column 
     [
        Text,
        Buttom,
        ListView
          ListItem
          ListItem
          ListItem
     ]

【讨论】:

恐怕将 ListView 放在 Text 和 Button 下的列内只会使 ListView 可滚动。我希望列中的所有内容都是可滚动的。 知道了。对于这种情况,条子很合适。恭喜【参考方案2】:

您可以在body中使用以下代码。

body: SingleChildScrollView( //add to Scroll whole screen
    child: Column(
        children: <Widget>[
            new Text('Some Text'), //Element-1
            new FlatButton(...),   //Element-2
            new Image.asset(...),  //Element-3
            items.map((item)=>new Padding(child: new Text(item.title),)).toList(), //Element-4
            ListView.separated(    //Element-5
                shrinkWrap: true,  //this property is must when you put List/Grid View inside SingleChildScrollView
                physics: NeverScrollableScrollPhysics(), //this property is must when you put List/Grid View inside SingleChildScrollView
                itemCount: listItems.length,
                itemBuilder: (context, i) 
                    return ListTile(
                        title: Text(listItems[i].Title),
                        subtitle: Text(listItems[i].Description),
                    );
                ,
                separatorBuilder: (context, i) 
                    return Divider();
                ,
            ),
        ],
    ),
),

【讨论】:

滚动listview时其他区域不滚动(文字和图片)【参考方案3】:

你可以这样使用

 ListView(
     shrinkWrap: true,
     children: <Widget>[
          Text('hi'),//first widget
          Text('hi2'),//second widget
          Flex(
              direction: Axis.horizontal,children: <Widget>[
                      Expanded(
                        child: ListView.builder(
                            shrinkWrap: true,
                            itemCount: 3,
                            itemBuilder: (BuildContext context, int index)
                              return ...

或者 只需调整计数和索引即可。

 ListView.builder(
      itemCount: get.length + 2, // add room for the two extra
      itemBuilder: (BuildContext context, int index) 
        if(index == 0)
         return Text('Custom any widget');
        
        if(index == 1)
         return Text('Custom any widget');
        
        index -= 2; // decrement index so that it's now in the range [0..length]
        return Bubble(
            style: styleSomebody,
            child: Container(
              ... 
            ));
      ),

【讨论】:

【参考方案4】:

您可以使用ListView.builder,因为它更有效,因为这些项目仅在它们滚动到屏幕上时才会创建。您可以将不在列表中的小部件放在第一个位置,如下所示:

@override
Widget build(BuildContext context) 
  return Scaffold(
    appBar: AppBar(title: Text('App bar')),
    body: ListView.builder(
      itemCount: items.length + 1,
      itemBuilder: (context, index) 
        if (index == 0) 
          return Column(
            children: <Widget>[
              Text('Some Text'),
              FlatButton(child: Text('A flat button'), onPressed: () ),
              Image.asset("An image"),
            ],
          );
        
        return Text('Item $items[index].title');
      ,
    ),
  );

【讨论】:

以上是关于Flutter ListView 与不同的小部件和列表项的主要内容,如果未能解决你的问题,请参考以下文章

在没有 ListView 等的情况下刷新 Flutter 中的小部件或页面

如何在 Flutter 的 ListView 中显示特定小部件的子小部件?

Flutter ListView.Builder() 在可滚动列中与其他小部件

ListView flutter 中如何管理不同小部件的状态?

在flutter中使用listview.builder添加多个彼此不同的动态小部件

Flutter:ListView inside Column inside Column