繁体   English   中英

如何在 ListView 中的 flutter 中创建一行可滚动的文本框或小部件?

[英]how to create a row of scrollable text boxes or widgets in flutter inside a ListView?

1.有人能告诉我如何在 ListView 中的 flutter 中创建一行可向左或向右滚动的文本框吗? 我可以看到我正在尝试在有限宽度的 ListView 中定义无限宽度。 但是,无法找出任何解决方法。

如果简单地在 customscrollview 中注释 scrolldirection 属性(即,将 scrolldirection 更改为垂直),则下面提到的代码绝对可以正常工作。 但是,我正在寻找水平滚动。 我试图解决这个问题,但没有运气。

有人可以帮忙,让我知道我哪里做错了。

  1. 另外,我们如何像在 flutter 中的 Android 中那样创建或扩充布局? 我已经包含了我正在创建的布局的屏幕截图以供参考:

1[在此处输入图片描述

我已经发布了下面的代码以重现相同的错误;

问候, 马希

  import 'package:flutter/material.dart';
  import 'package:flutter/rendering.dart';
   import 'package:flutter/widgets.dart';
       void main(){
       runApp(new AddNewBlock());
       }

 class AddNewBlock extends StatefulWidget{

@override
State<StatefulWidget> createState() {
return new _AddNewBlockState();
    }
  }

   class _AddNewBlockState extends State<AddNewBlock>{


    @override
   Widget build(BuildContext context) {
   return new MaterialApp(
            title: 'Add New Block',
  debugShowCheckedModeBanner: false,

  home: new Scaffold(

    body: new ListView(
      shrinkWrap: true,

      children: <Widget>[
        new Container(
          margin: const EdgeInsets.only(
            left: 16.0,top: 24.0, bottom: 8.0,
          ),
          child: new Text(
            'Add New Block',
          style: new TextStyle(
            fontSize: 18.0,
            fontWeight: FontWeight.bold,
            color: Colors.teal[300],
    ),
          ),
        ),
        new Container(
          margin: const EdgeInsets.only(left: 16.0, top: 16.0, bottom: 8.0),
          child: new Text ('Block Name'),
        ),

        new Container(
          margin: const EdgeInsets.fromLTRB(16.0, 8.0, 0.0, 8.0),
          child: new Text ('Block A1',
          style: new TextStyle(
            fontSize: 16.0,
            fontWeight: FontWeight.bold
          ),),
        ),
        new Divider(color: Colors.grey,),
        new Container(
          margin: const EdgeInsets.only(left: 16.0, top: 8.0,bottom: 8.0),
          child: new Text('NO. OF FLOORS',
          style: new TextStyle(
            fontSize: 12.0,
          ),
          ),
        ),



       new Container(
                    child: new Row(
                      children: <Widget>[
                        new Flexible(
                          child: new CustomScrollView(
                            shrinkWrap: true,
                            scrollDirection: Axis.horizontal,
                            slivers: <Widget>[
                          new SliverPadding(
                          padding: const EdgeInsets.all(20.0),
                          sliver: new SliverList(
                            delegate: new SliverChildListDelegate(
                              <Widget>[
                                const Text('this'),
                                const Text('is'),
                                const Text('scroll'),
                                const Text('view'),
                                const Text('inside'),
                                const Text('list'),
                                const Text('view'),
                                const Text('in'),
                                const Text('horizontal'),
                                const Text('direction')
                              ],
                            ),
                          ),
                        ),
                      ],
                          ),
                        ),
                      ],
                    ),
                  ),





      ],

    ),
  ),


  );
   }
}

我认为这很简单,只要您在水平ListView上放置一个固定高度的容器。 但也许我不明白你的问题。 如果这不起作用,请发布您的代码和您收到的错误消息。

截屏

import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import 'dart:collection';

void main() {
  runApp(new MaterialApp(home: new DemoApp()));
}

class DemoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text('Nested ListView Example')),
      body: new Center(
        child: new ListView(
          children: <Widget>[
            new Container(
              height: 80.0,
              child: new ListView(
                scrollDirection: Axis.horizontal,
                children: new List.generate(10, (int index) {
                  return new Card(
                    color: Colors.blue[index * 100],
                    child: new Container(
                      width: 50.0,
                      height: 50.0,
                      child: new Text("$index"),
                    ),
                  );
                }),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

我这样做是为了使我的 Row 小部件可滚动:

Text("Debilidades",
    style: TextStyle(fontWeight: FontWeight.bold)),
SingleChildScrollView(
  scrollDirection: Axis.horizontal,
  padding: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0.0),
  child: Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: pokemon.weaknesses == null
          ? <Widget>[
              Text(
                "No tiene debilidades",
                style: TextStyle(color: Colors.grey),
              )
            ]
          : pokemon.weaknesses
              .map((weakness) => FilterChip(
                  backgroundColor: Colors.red,
                  label: Text(
                    weakness,
                    style: TextStyle(color: Colors.white),
                  ),

                  onSelected: (b) {}))
              .toList()),
),

在此处输入图片说明

对于要滚动的行/列,您只需使用SingleChildScrollView功能并根据需要提及方向。

SingleChildScrollView(
    scrollDirection: Axis.horizontal,
    child: Row(
        children: [
            //provide all the things u want to horizontally scroll here
        ]
    ),
);

您可以使用:

@override
Widget build(BuildContext context) {
  return Column(
    children: <Widget>[
      SizedBox( // Horizontal ListView
        height: 100,
        child: ListView.builder(
          itemCount: 20,
          scrollDirection: Axis.horizontal,
          itemBuilder: (context, index) {
            return Container(
              width: 100,
              alignment: Alignment.center,
              color: Colors.blue[(index % 9) * 100],
              child: Text(index.toString()),
            );
          },
        ),
      ),
      SizedBox( // Vertical ListView
        height: 200,
        child: ListView.builder(
          itemCount: 20,
          itemBuilder: (context, index) {
            return Container(
              width: 50,
              height: 50,
              alignment: Alignment.center,
              color: Colors.orange[(index % 9) * 100],
              child: Text(index.toString()),
            );
          },
        ),
      ),
    ],
  );
}

注意:为简单起见,我没有在单个 Widget 中重构两个ListView

输出

在此处输入图片说明

我通过使用ListView.builder()设法做到了这一点

这是完整的代码:

import 'package:flutter/material.dart';


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

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text("Scroll on the Horizon"),
          centerTitle: true,
        ),
        body: new ListView.builder(
          scrollDirection: Axis.horizontal,
          itemBuilder: (BuildContext context, int index) {
            return new Row(
              children: <Widget>[
                new Text("Let ", style: new TextStyle(color: Colors.blue),),
                new Text("me ", style: new TextStyle(color: Colors.red)),
                new Text("scroll ", style: new TextStyle(color: Colors.green)),
                new Text("horizontally ",
                    style: new TextStyle(color: Colors.orange)),
                new Text("Let ", style: new TextStyle(color: Colors.blue),),
                new Text("me ", style: new TextStyle(color: Colors.red)),
                new Text("scroll ", style: new TextStyle(color: Colors.green)),
                new Text("horizontally ",
                    style: new TextStyle(color: Colors.orange)),
                new Text("Let ", style: new TextStyle(color: Colors.blue),),
                new Text("me ", style: new TextStyle(color: Colors.red)),
                new Text("scroll ", style: new TextStyle(color: Colors.green)),
                new Text("horizontally ",
                    style: new TextStyle(color: Colors.orange)),
                new Text("Let ", style: new TextStyle(color: Colors.blue),),
                new Text("me ", style: new TextStyle(color: Colors.red)),
                new Text("scroll ", style: new TextStyle(color: Colors.green)),
                new Text("horizontally ",
                    style: new TextStyle(color: Colors.orange)),

              ],

            );
          },


        ));
  }

}

不要忘记将scrollDirection属性设置为Axis.horizontal ,因为它默认为vertical值。

您可能想要创建嵌套 ListView

为了尝试这个例子,你需要做的就是将下面的代码复制粘贴到你新创建的 flutter 项目的 main.dart 文件中。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = "Nested ListView List";

    List<Choice> choices = const <Choice>[
      const Choice(
          title: 'MacBook Pro',
          date: '1 June 2019',
          description:
          'MacBook Pro (sometimes abbreviated as MBP) is a line of Macintosh portable computers introduced in January 2006 by Apple Inc.',
          imglink:
          'https://images.unsplash.com/photo-1517694712202-14dd9538aa97?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60'),
      const Choice(
          title: 'MacBook Air',
          date: '1 June 2016',
          description:
          'MacBook Air is a line of laptop computers developed and manufactured by Apple Inc. It consists of a full-size keyboard, a machined aluminum case, and a thin light structure.',
          imglink:
          'https://images.unsplash.com/photo-1499673610122-01c7122c5dcb?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60'),
      const Choice(
          title: 'iMac',
          date: '1 June 2019',
          description:
          'iMac is a family of all-in-one Macintosh desktop computers designed and built by Apple Inc. It has been the primary part of Apple consumer desktop offerings since its debut in August 1998, and has evolved through seven distinct forms.',
          imglink:
          'https://images.unsplash.com/photo-1517059224940-d4af9eec41b7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60'),
      const Choice(
          title: 'Mac Mini',
          date: '1 June 2017',
          description:
          'Mac mini (branded with lowercase "mini") is a desktop computer made by Apple Inc. One of four desktop computers in the current Macintosh lineup, along with the iMac, Mac Pro, and iMac Pro, it uses many components usually featured in laptops to achieve its small size.',
          imglink:
          'https://www.apple.com/v/mac-mini/f/images/shared/og_image__4mdtjbfhcduu_large.png?201904170831'),
      const Choice(
          title: 'Mac Pro',
          date: '1 June 2018',
          description:
          'Mac Pro is a series of workstation and server computer cases designed, manufactured and sold by Apple Inc. since 2006. The Mac Pro, in most configurations and in terms of speed and performance, is the most powerful computer that Apple offers.',
          imglink:
          'https://i0.wp.com/9to5mac.com/wp-content/uploads/sites/6/2017/01/mac-pro-2-concept-image.png?resize=1000%2C500&quality=82&strip=all&ssl=1'),
    ];

    return MaterialApp(
        title: title,
        home: Scaffold(
            appBar: AppBar(
              title: Text(title),
            ),
            body:
            ListView(
                children: [
                  Container(
                    height: 300.0,
                    child: ListView(
                        scrollDirection: Axis.horizontal,
                        shrinkWrap: true,
                        padding: const EdgeInsets.all(20.0),
                        children: List.generate(choices.length, (index) {
                          return Center(
                            child: ChoiceCard(
                                choice: choices[index], item: choices[index]),
                          );
                        })),
                  ),
                  Container(
                    height: 300.0,

                    child: ListView(
                        scrollDirection: Axis.horizontal,
                        shrinkWrap: true,
                        padding: const EdgeInsets.all(20.0),
                        children: List.generate(choices.length, (index) {
                          return Center(
                            child: ChoiceCard(
                                choice: choices[index], item: choices[index]),
                          );
                        })),
                  ),
                  Container(
                    height: 300.0,

                    child: ListView(
                        scrollDirection: Axis.horizontal,
                        shrinkWrap: true,
                        padding: const EdgeInsets.all(20.0),
                        children: List.generate(choices.length, (index) {
                          return Center(
                            child: ChoiceCard(
                                choice: choices[index], item: choices[index]),
                          );
                        })),
                  ),
                ])));
  }
}

class Choice {
  final String title;
  final String date;
  final String description;
  final String imglink;

  const Choice({this.title, this.date, this.description, this.imglink});
}

class ChoiceCard extends StatelessWidget {
  const ChoiceCard(
      {Key key,
        this.choice,
        this.onTap,
        @required this.item,
        this.selected: false})
      : super(key: key);

  final Choice choice;
  final VoidCallback onTap;
  final Choice item;
  final bool selected;

  @override
  Widget build(BuildContext context) {
    TextStyle textStyle = Theme.of(context).textTheme.display1;
    if (selected)
      textStyle = textStyle.copyWith(color: Colors.lightGreenAccent[400]);
    return Card(
        color: Colors.white,
        child: Column(
          children: <Widget>[
            new Expanded(
                child: Container(
                  width: 260.0,
                  height: 260.0,
                  child: Image.network(choice.imglink),
                )),
            new Container(
              width: 260.0,
              padding: const EdgeInsets.all(10.0),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Text(choice.title, style: Theme.of(context).textTheme.title),
                  Text(choice.date,
                      style: TextStyle(color: Colors.black.withOpacity(0.5))),
                  Text(choice.description),
                ],
              ),
            )
          ],
          crossAxisAlignment: CrossAxisAlignment.start,
        ));
  }
}

在此处输入图片说明

基于: 嵌套列表视图

有多种方法可以在垂直 ListView 中显示水平 ListView

  1. 使用带有 SingleChildScrollView 的 Row 小部件
SingleChildScrollView(
  scrollDirection: Axis.horizontal,
  child: Row(
    children: List.generate(20, (x) => _listItem(x.toString()))
      .toList())),

或者,如果您有一个 List,那么您可以映射它并渲染它以代替 List.generate。 下面的示例假设 UserModel 具有属性“firstName”。

e.g
List<UserModel> _list;
SingleChildScrollView(
   scrollDirection: Axis.horizontal,
   child: Row(
     children: _list.map((e) => _listItem(e.firstName)).toList())),
  1. 使用水平 ListView.builder
Container(
  height:50,// requires a finite vertical height  
  child: ListView.builder(
    itemCount: 50,
    scrollDirection: Axis.horizontal,
    itemBuilder: (_, index) => _listItem(index.toString())),
),
  1. 使用水平 ListView
ConstrainedBox(
  constraints: BoxConstraints(maxHeight: 50), // requires vertical bounded height
  child: ListView(
    scrollDirection: Axis.horizontal,
    children: List.generate(20, (x) => _listItem(x.toString()))
      .toList()),
),

我使用带有水平滚动方向的 SingleChildScrollView 包裹的 Row 小部件实现了这一点,然后,我用另一行包裹了我的行小部件,以便添加一个大小的框小部件以在这些小部件之间形成间距。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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